-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support natural language search for k8s resources (#612)
## What type of PR is this? /kind feature ## What this PR does / why we need it: Integrating AI into our product to reduce the consumption of human attention is a significant milestone for us in the upcoming versions. This PR can be a very good start to build anything related to AI. Purpose: - Support an AI backend service that other modules can use to access AI language models. - Add a new search way: natural language search based on large language models. ## Which issue(s) this PR fixes: <!-- *Automatically closes linked issue when PR is merged. Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. _If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_* --> Fixes #452 --------- Co-authored-by: 玦离 <[email protected]> Co-authored-by: hai-tian <[email protected]>
- Loading branch information
1 parent
ab3196b
commit 2b45db9
Showing
30 changed files
with
1,456 additions
and
436 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright The Karpor Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package options | ||
|
||
import ( | ||
"github.com/KusionStack/karpor/pkg/kubernetes/registry" | ||
"github.com/spf13/pflag" | ||
) | ||
|
||
type AIOptions struct { | ||
AIBackend string | ||
AIAuthToken string | ||
AIBaseURL string | ||
AIModel string | ||
AITemperature float32 | ||
AITopP float32 | ||
} | ||
|
||
const ( | ||
defaultBackend = "openai" | ||
defaultModel = "gpt-3.5-turbo" | ||
defaultTemperature = 1 | ||
defaultTopP = 1 | ||
) | ||
|
||
func NewAIOptions() *AIOptions { | ||
return &AIOptions{} | ||
} | ||
|
||
func (o *AIOptions) Validate() []error { | ||
return nil | ||
} | ||
|
||
func (o *AIOptions) ApplyTo(config *registry.ExtraConfig) error { | ||
// Apply the AIOptions to the provided config | ||
config.AIBackend = o.AIBackend | ||
config.AIAuthToken = o.AIAuthToken | ||
config.AIBaseURL = o.AIBaseURL | ||
config.AIModel = o.AIModel | ||
config.AITemperature = o.AITemperature | ||
config.AITopP = o.AITopP | ||
return nil | ||
} | ||
|
||
// AddFlags adds flags for a specific Option to the specified FlagSet | ||
func (o *AIOptions) AddFlags(fs *pflag.FlagSet) { | ||
if o == nil { | ||
return | ||
} | ||
|
||
fs.StringVar(&o.AIBackend, "ai-backend", defaultBackend, "The ai backend") | ||
fs.StringVar(&o.AIAuthToken, "ai-auth-token", "", "The ai auth token") | ||
fs.StringVar(&o.AIBaseURL, "ai-base-url", "", "The ai base url") | ||
fs.StringVar(&o.AIModel, "ai-model", defaultModel, "The ai model") | ||
fs.Float32Var(&o.AITemperature, "ai-temperature", defaultTemperature, "The ai temperature") | ||
fs.Float32Var(&o.AITopP, "ai-top-p", defaultTopP, "The ai top-p") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright The Karpor Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ai | ||
|
||
import ( | ||
"github.com/KusionStack/karpor/pkg/infra/ai" | ||
"github.com/KusionStack/karpor/pkg/kubernetes/registry" | ||
) | ||
|
||
type AIManager struct { | ||
client ai.AIProvider | ||
} | ||
|
||
// NewAIManager returns a new AIManager object | ||
func NewAIManager(c registry.ExtraConfig) (*AIManager, error) { | ||
if c.AIAuthToken == "" { | ||
return nil, ErrMissingAuthToken | ||
} | ||
aiClient := ai.NewClient(c.AIBackend) | ||
if err := aiClient.Configure(ai.ConvertToAIConfig(c)); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &AIManager{ | ||
client: aiClient, | ||
}, nil | ||
} | ||
|
||
// CheckAIManager check if the AI manager is created | ||
func CheckAIManager(aiMgr *AIManager) error { | ||
if aiMgr == nil { | ||
return ErrMissingAuthToken | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright The Karpor Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ai | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/KusionStack/karpor/pkg/infra/ai" | ||
) | ||
|
||
// ConvertTextToSQL converts natural language text to an SQL query | ||
func (a *AIManager) ConvertTextToSQL(query string) (string, error) { | ||
servicePrompt := ai.ServicePromptMap[ai.Text2sqlType] | ||
prompt := fmt.Sprintf(servicePrompt, query) | ||
res, err := a.client.Generate(context.Background(), prompt) | ||
if err != nil { | ||
return "", err | ||
} | ||
if IsInvalidQuery(res) { | ||
return "", ErrInvalidQuery | ||
} | ||
return ExtractSelectSQL(res), nil | ||
} | ||
|
||
// FixSQL fix the error SQL | ||
func (a *AIManager) FixSQL(sql string, query string, sqlErr string) (string, error) { | ||
servicePrompt := ai.ServicePromptMap[ai.SQLFixType] | ||
prompt := fmt.Sprintf(servicePrompt, query, sql, sqlErr) | ||
res, err := a.client.Generate(context.Background(), prompt) | ||
if err != nil { | ||
return "", err | ||
} | ||
return ExtractSelectSQL(res), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright The Karpor Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ai | ||
|
||
import "errors" | ||
|
||
var ( | ||
ErrMissingAuthToken = errors.New("auth token is required") | ||
ErrInvalidQuery = errors.New("query is invalid") | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Copyright The Karpor Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ai | ||
|
||
import ( | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
// IsInvalidQuery check if the query is invalid | ||
func IsInvalidQuery(sql string) bool { | ||
return strings.Contains(strings.ToLower(sql), "error") | ||
} | ||
|
||
// ExtractSelectSQL extracts SQL statements that start with "SELECT * FROM" | ||
func ExtractSelectSQL(sql string) string { | ||
res := regexp.MustCompile(`(?i)SELECT \* FROM [^;]+`) | ||
match := res.FindString(sql) | ||
return match | ||
} |
Oops, something went wrong.