diff --git a/pkg/functions/parse.go b/pkg/functions/parse.go
index ef81242b..3d08ef56 100644
--- a/pkg/functions/parse.go
+++ b/pkg/functions/parse.go
@@ -37,7 +37,7 @@ type FunctionsConfig struct {
ResponseRegex string `yaml:"response_regex"`
// JSONRegexMatch is a regex to extract the JSON object from the response
- JSONRegexMatch string `yaml:"json_regex_match"`
+ JSONRegexMatch []string `yaml:"json_regex_match"`
// GrammarPrefix is the suffix to append to the grammar when being generated
// This is useful when models prepend a tag before returning JSON
@@ -124,6 +124,18 @@ func ParseFunctionCall(llmresult string, functionConfig FunctionsConfig) []FuncC
// the response is a string that we have to parse
result := make(map[string]string)
+ if len(functionConfig.JSONRegexMatch) != 0 {
+ for _, r := range functionConfig.JSONRegexMatch {
+ // We use a regex to extract the JSON object from the response
+ var respRegex = regexp.MustCompile(r)
+ match := respRegex.FindStringSubmatch(llmresult)
+ if len(match) >= 2 {
+ llmresult = match[1]
+ break
+ }
+ }
+ }
+
if functionConfig.ResponseRegex != "" {
// We use named regexes here to extract the function name and arguments
// obviously, this expects the LLM to be stable and return correctly formatted JSON
@@ -143,16 +155,6 @@ func ParseFunctionCall(llmresult string, functionConfig FunctionsConfig) []FuncC
return results
}
results = append(results, FuncCallResults{Name: result[functionNameKey], Arguments: result["arguments"]})
- } else if functionConfig.JSONRegexMatch != "" {
-
- // We use a regex to extract the JSON object from the response
- var respRegex = regexp.MustCompile(functionConfig.JSONRegexMatch)
- match := respRegex.FindStringSubmatch(llmresult)
- if len(match) < 2 {
- return results
- }
-
- results, _ = returnResult(match[1])
} else {
results, _ = returnResult(llmresult)
}
diff --git a/pkg/functions/parse_test.go b/pkg/functions/parse_test.go
index 14e27870..58c2c2bb 100644
--- a/pkg/functions/parse_test.go
+++ b/pkg/functions/parse_test.go
@@ -91,7 +91,7 @@ var _ = Describe("LocalAI function parse tests", func() {
{"function": "add", "arguments": {"x": 5, "y": 3}}
`
- functionConfig.JSONRegexMatch = `(?s)(.*?)`
+ functionConfig.JSONRegexMatch = []string{`(?s)(.*?)`}
results := ParseFunctionCall(input, functionConfig)
Expect(results).To(HaveLen(1))
@@ -104,7 +104,7 @@ var _ = Describe("LocalAI function parse tests", func() {
{"function": "add", "arguments": {"x": 5, "y": 3}}
`
- functionConfig.JSONRegexMatch = `(?s)(.*?)`
+ functionConfig.JSONRegexMatch = []string{`(?s)(.*?)`}
results := ParseFunctionCall(input, functionConfig)
Expect(results).To(HaveLen(1))
@@ -157,6 +157,41 @@ Some text before the JSON
{'function': '"add"', 'arguments': {'x': 5, 'z': '"v"', 'y': 'v"value"'}}
Some text after the JSON
`
+ functionConfig.JSONRegexMatch = []string{`(?s)(.*?)`}
+
+ // Regex to match non-JSON characters before the JSON structure
+ //reBefore := regexp.MustCompile(`(?s)^.*?(?=\{|\[)`)
+ // Regex to match non-JSON characters after the JSON structure
+ //reAfter := regexp.MustCompile(`(?s)(?<=\}|\]).*$`)
+
+ functionConfig.ReplaceResults = yaml.MapSlice{
+ {Key: `(?s)^[^{\[]*`, Value: ""},
+ {Key: `(?s)[^}\]]*$`, Value: ""},
+ // Regex pattern to match single quotes around keys and values
+ // Step 1: Replace single quotes around keys and values with double quotes
+ {Key: `'([^']*?)'`, Value: `_DQUOTE_${1}_DQUOTE_`},
+ // Step 2: Replace double quotes inside values with placeholders
+ {Key: `\\"`, Value: `__TEMP_QUOTE__`},
+ {Key: `"`, Value: `\"`},
+ {Key: `\'`, Value: `'`},
+ {Key: `_DQUOTE_`, Value: `"`},
+ {Key: `__TEMP_QUOTE__`, Value: `"`},
+ }
+
+ results := ParseFunctionCall(input, functionConfig)
+ Expect(results).To(HaveLen(1))
+ Expect(results[0].Name).To(Equal("\"add\""))
+ Expect(results[0].Arguments).To(Equal(`{"x":5,"y":"v\"value\"","z":"\"v\""}`))
+ })
+
+ It("should convert single-quoted key-value pairs to double-quoted and escape double quotes within values", func() {
+ input := `
+Some text before the JSON
+{'function': '"add"', 'arguments': {'x': 5, 'z': '"v"', 'y': 'v"value"'}}
+Some text after the JSON
+`
+ functionConfig.JSONRegexMatch = []string{`(?s)(.*?)`}
+
// Regex to match non-JSON characters before the JSON structure
//reBefore := regexp.MustCompile(`(?s)^.*?(?=\{|\[)`)
// Regex to match non-JSON characters after the JSON structure