mirror of
https://github.com/mudler/LocalAI.git
synced 2025-02-20 17:32:47 +00:00
feat(functions): support models with no grammar and no regex (#2315)
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
parent
4ac7956f68
commit
c4186f13c3
@ -41,24 +41,33 @@ func ParseFunctionCall(llmresult string, functionConfig FunctionsConfig) []FuncC
|
||||
// if no grammar is used, we have to extract function and arguments from the result
|
||||
if !useGrammars {
|
||||
// the response is a string that we have to parse
|
||||
|
||||
// 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
|
||||
// TODO: optimize this and pre-compile it
|
||||
var respRegex = regexp.MustCompile(functionConfig.ResponseRegex)
|
||||
match := respRegex.FindStringSubmatch(llmresult)
|
||||
result := make(map[string]string)
|
||||
for i, name := range respRegex.SubexpNames() {
|
||||
if i != 0 && name != "" && len(match) > i {
|
||||
result[name] = match[i]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: open point about multiple results and/or mixed with chat messages
|
||||
// This is not handled as for now, we only expect one function call per response
|
||||
functionName := result[functionNameKey]
|
||||
if functionName == "" {
|
||||
return results
|
||||
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
|
||||
// TODO: optimize this and pre-compile it
|
||||
var respRegex = regexp.MustCompile(functionConfig.ResponseRegex)
|
||||
match := respRegex.FindStringSubmatch(llmresult)
|
||||
for i, name := range respRegex.SubexpNames() {
|
||||
if i != 0 && name != "" && len(match) > i {
|
||||
result[name] = match[i]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: open point about multiple results and/or mixed with chat messages
|
||||
// This is not handled as for now, we only expect one function call per response
|
||||
functionName := result[functionNameKey]
|
||||
if functionName == "" {
|
||||
return results
|
||||
}
|
||||
} else {
|
||||
// We expect the result to be a JSON object with a function name and arguments
|
||||
err := json.Unmarshal([]byte(llmresult), &result)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("llmresult", llmresult).Msg("unable to unmarshal llm result")
|
||||
return results
|
||||
}
|
||||
}
|
||||
|
||||
return append(results, FuncCallResults{Name: result[functionNameKey], Arguments: result["arguments"]})
|
||||
|
@ -82,4 +82,32 @@ var _ = Describe("LocalAI function parse tests", func() {
|
||||
Expect(results[1].Arguments).To(Equal(`{"x":10,"y":7}`))
|
||||
})
|
||||
})
|
||||
|
||||
Context("without grammars and without regex", func() {
|
||||
It("should parse the function name and arguments correctly with the name key", func() {
|
||||
input := `{"name": "add", "arguments": {"x": 5, "y": 3}}`
|
||||
functionConfig.ParallelCalls = false
|
||||
functionConfig.NoGrammar = false
|
||||
functionConfig.ResponseRegex = ""
|
||||
functionConfig.FunctionName = true
|
||||
|
||||
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":3}`))
|
||||
})
|
||||
|
||||
It("should parse the function name and arguments correctly with the function key", func() {
|
||||
input := `{"function": "add", "arguments": {"x": 5, "y": 3}}`
|
||||
functionConfig.ParallelCalls = false
|
||||
functionConfig.NoGrammar = false
|
||||
functionConfig.ResponseRegex = ""
|
||||
functionConfig.FunctionName = false
|
||||
|
||||
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":3}`))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user