Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Addressing comments
  • Loading branch information
totoleon authored and kurtisvg committed Apr 4, 2025
commit 2ff0bf99dc4b56220e90be882a3dac90ca7493ae
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,40 @@ title: "alloydb-ai-nl"
type: docs
weight: 1
Comment thread
totoleon marked this conversation as resolved.
Outdated
description: >
A "alloydb-ai-nl" tool leverages AlloyDB's AI functions to execute natural language questions against the database.
The "alloydb-ai-nl" tool leverages AlloyDB's AI next-generation
Comment thread
kurtisvg marked this conversation as resolved.
Outdated
[AI natural language]([alloydb-ai-nl-overview] support to provide the
ability to query the database directly using natural language.
---

## About

A `alloydb-ai-nl` tool leverages AlloyDB's AI functions to execute natural language questions against the database. It allows users to query database information using natural language instead of SQL. It's compatible with the following sources:
The "alloydb-ai-nl" tool leverages AlloyDB's next-generation AI natural
language feature to allow an Agent the ability to query the database directly
using natural language. Natural language streamlines the development of
generative AI applications by transferring the complexity of converting
natural language to SQL from the application layer to the database layer.

This tool is compatible with the following sources:
- [alloydb-postgres](../sources/alloydb-pg.md)

The tool uses AlloyDB's natural language processing capabilities to interpret questions and convert them into appropriate SQL queries, which are then executed against the database. TODO: link to AlloyDB's documentation.
AlloyDB AI natural language delivers secure and accurate responses for
application end user natural language questions. Natural language streamlines
the development of generative AI applications by transferring the complexity
of converting natural language to SQL from the application layer to the
database layer.

Comment thread
Yuan325 marked this conversation as resolved.
Outdated
## Fields

`nlConfig` is the name of the `nl_config` created in AlloyDB.

`nlConfigParameters` are the list of the parameters and values for the AlloyDB [PSV (parameterized secure views)](!https://cloud.google.com/alloydb/docs/ai/use-psvs#sanitize_queries_with_parameterized_secure_views).
`nlConfigParameters` are the list of the parameters and values for the AlloyDB
[PSV (parameterized secure views)](!https://cloud.google.com/alloydb/docs/ai/use-psvs#sanitize_queries_with_parameterized_secure_views).

When using this tool, all the PSV parameters should be from filled with values from an auth service or a bounded param. These parameters should not be visible to the LLM agent. Instead, the LLM will only see one argument when using this tool - `question`, with the description being "The natural language question to ask."
When using this tool, all the PSV parameters should be from filled with values
from an auth service or a bounded param. These parameters should not be
visible to the LLM agent. Instead, the LLM will only see one argument when
using this tool - `question`, with the description being "The natural
language question to ask."

## Example

Expand Down
6 changes: 3 additions & 3 deletions internal/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import (
"github.com/googleapis/genai-toolbox/internal/tools/mysqlsql"
neo4jtool "github.com/googleapis/genai-toolbox/internal/tools/neo4j"
"github.com/googleapis/genai-toolbox/internal/tools/postgressql"
"github.com/googleapis/genai-toolbox/internal/tools/alloydbnla"
"github.com/googleapis/genai-toolbox/internal/tools/alloydbainl"
"github.com/googleapis/genai-toolbox/internal/tools/spanner"
"github.com/googleapis/genai-toolbox/internal/util"
)
Expand Down Expand Up @@ -308,8 +308,8 @@ func (c *ToolConfigs) UnmarshalYAML(ctx context.Context, unmarshal func(interfac
return fmt.Errorf("unable to parse as %q: %w", kind, err)
}
(*c)[name] = actual
case alloydbnla.ToolKind:
actual := alloydbnla.Config{Name: name}
case alloydbainl.ToolKind:
actual := alloydbainl.Config{Name: name}
if err := dec.DecodeContext(ctx, &actual); err != nil {
return fmt.Errorf("unable to parse as %q: %w", kind, err)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 Google LLC
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package alloydbnla
package alloydbainl

import (
"context"
Expand Down Expand Up @@ -66,39 +66,40 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
return nil, fmt.Errorf("invalid source for %q tool: source kind must be one of %q", ToolKind, compatibleSources)
}

paramNames := make([]string, 0, len(cfg.NLConfigParameters))
for _, paramDef := range cfg.NLConfigParameters {
paramNames = append(paramNames, paramDef.GetName())
}
quotedParamNames := make([]string, len(paramNames))
for i, name := range paramNames {
// Basic escaping for single quotes within the name itself
escapedName := strings.ReplaceAll(name, "'", "''")
quotedParamNames[i] = fmt.Sprintf("'%s'", escapedName)
}
paramNamesSQL := "ARRAY []" // Default for no parameters
if len(quotedParamNames) > 0 {
paramNamesSQL = fmt.Sprintf("ARRAY [%s]", strings.Join(quotedParamNames, ", "))
}
paramValuePlaceholders := make([]string, len(paramNames))
for i := 0; i < len(paramNames); i++ {
// Placeholders start from $2 ($1 is reserved for the natural language query)
paramValuePlaceholders[i] = fmt.Sprintf("$%d", i+2)
numParams := len(cfg.NLConfigParameters)
quotedNameParts := make([]string, 0, numParams)
placeholderParts := make([]string, 0, numParams)

for i, paramDef := range cfg.NLConfigParameters {
name := paramDef.GetName()
escapedName := strings.ReplaceAll(name, "'", "''") // Escape for SQL literal
quotedNameParts = append(quotedNameParts, fmt.Sprintf("'%s'", escapedName))
placeholderParts = append(placeholderParts, fmt.Sprintf("$%d", i+2)) // $1 reserved
}
paramValuesSQL := "ARRAY []" // Default for no parameters
if len(paramValuePlaceholders) > 0 {
paramValuesSQL = fmt.Sprintf("ARRAY [%s]", strings.Join(paramValuePlaceholders, ", "))

var paramNamesSQL string
var paramValuesSQL string

if numParams > 0 {
paramNamesSQL = fmt.Sprintf("ARRAY[%s]", strings.Join(quotedNameParts, ", "))
paramValuesSQL = fmt.Sprintf("ARRAY[%s]", strings.Join(placeholderParts, ", "))
} else {
paramNamesSQL = "ARRAY[]::TEXT[]"
paramValuesSQL = "ARRAY[]::TEXT[]"
}

// execute_nl_query is the AlloyDB AI function that executes the natural language query
// The first parameter is the natural language query, which is passed as $1
// The second parameter is the NLConfig, which is passed as a string
// The third and fourth parameters are the list of nl_config parameter names and values, respectively
// The following params are the list of nl_config parameter names and values, respectively
// Example SQL statement being executed:
// SELECT alloydb_ai_nl.execute_nl_query('How many tickets do I have?', 'cymbal_air_nl_config', param_names => ARRAY ['user_email'], param_values => ARRAY ['hailongli@google.com']);
stmtFormat := "SELECT alloydb_ai_nl.execute_nl_query($1, '%s', param_names => %s, param_values => %s);"
stmt := fmt.Sprintf(stmtFormat, cfg.NLConfig, paramNamesSQL, paramValuesSQL)


newQuestionParam := tools.NewStringParameter(
"question", // name
"question", // name
"The natural language question to ask.", // description
)
Comment thread
totoleon marked this conversation as resolved.
Comment thread
totoleon marked this conversation as resolved.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package alloydbnla_test
package alloydbainl_test

import (
"testing"
Expand All @@ -22,7 +22,7 @@ import (
"github.com/googleapis/genai-toolbox/internal/server"
"github.com/googleapis/genai-toolbox/internal/testutils"
"github.com/googleapis/genai-toolbox/internal/tools"
"github.com/googleapis/genai-toolbox/internal/tools/alloydbnla"
"github.com/googleapis/genai-toolbox/internal/tools/alloydbainl"
)

func TestParseFromYamlAlloyDBNLA(t *testing.T) {
Expand Down Expand Up @@ -55,9 +55,9 @@ func TestParseFromYamlAlloyDBNLA(t *testing.T) {
field: sub
`,
want: server.ToolConfigs{
"example_tool": alloydbnla.Config{
"example_tool": alloydbainl.Config{
Name: "example_tool",
Kind: alloydbnla.ToolKind,
Kind: alloydbainl.ToolKind,
Source: "my-alloydb-instance",
Description: "AlloyDB natural language query tool",
NLConfig: "my_nl_config",
Expand Down Expand Up @@ -96,9 +96,9 @@ func TestParseFromYamlAlloyDBNLA(t *testing.T) {
field: user_email
`,
want: server.ToolConfigs{
"complex_tool": alloydbnla.Config{
"complex_tool": alloydbainl.Config{
Name: "complex_tool",
Kind: alloydbnla.ToolKind,
Kind: alloydbainl.ToolKind,
Source: "my-alloydb-instance",
Description: "AlloyDB natural language query tool with multiple parameters",
NLConfig: "complex_nl_config",
Expand Down