Skip to content

Commit ab8d2fe

Browse files
feat: implementation of semanticly retrieved dynamic toolsets (#818)
- Implements experimental dynamic tool selection through `Gram-Mode` header `semantic_search` | `progressive_search` - question should we call this mode `semantic` instead? - Vector storage and semantic search of toolsets is done via pgvector, all encapsulated into the `rag/search_tools.go` client. - For embedding this will be done through openrouter base client right now using the `text-embedding-3-small` - Given this is experimental and a toolset cannot be marked as dynamic. Indexing is done on demand as necessary in find_tools. We do not need to reindex if we recognize there has been no change to the toolset version or tools. Even in cases where toolset indexing is necessary it is still quite fast, easily under a second (spans tracking) - Right now we just hard delete old embeddings. There is no immediate reason to keep them around so it preserves space. The data model is setup for soft deletions Following this we'll complete a documentation page on these experimental modes and start our own testing across large toolsets between different modes.
1 parent 2f6f870 commit ab8d2fe

File tree

30 files changed

+2780
-2169
lines changed

30 files changed

+2780
-2169
lines changed

.changeset/light-meals-beam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"server": patch
3+
---
4+
5+
adds experimental gram-mode:embedding for dynamic MCP tool selection based on semantic search

server/cmd/gram/start.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/sourcegraph/conc/pool"
1919
"github.com/speakeasy-api/gram/server/internal/logs"
2020
"github.com/speakeasy-api/gram/server/internal/productfeatures"
21+
"github.com/speakeasy-api/gram/server/internal/rag"
2122
"github.com/urfave/cli/v2"
2223
"github.com/urfave/cli/v2/altsrc"
2324
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
@@ -516,6 +517,7 @@ func newStartCommand() *cli.Command {
516517
shutdownFuncs = append(shutdownFuncs, shutdown)
517518

518519
chatClient := chat.NewChatClient(logger, tracerProvider, meterProvider, db, openRouter, baseChatClient, env, encryptionClient, cache.NewRedisCacheAdapter(redisClient), guardianPolicy, functionsOrchestrator)
520+
ragService := rag.NewToolsetVectorStore(tracerProvider, db, baseChatClient)
519521
mux := goahttp.NewMuxer()
520522

521523
mux.Use(middleware.CORSMiddleware(c.String("environment"), c.String("server-url")))
@@ -550,7 +552,7 @@ func newStartCommand() *cli.Command {
550552
instances.Attach(mux, instances.NewService(logger, tracerProvider, meterProvider, db, sessionManager, env, encryptionClient, cache.NewRedisCacheAdapter(redisClient), guardianPolicy, functionsOrchestrator, billingTracker, tcm))
551553
mcpMetadataService := mcpmetadata.NewService(logger, db, sessionManager, serverURL, siteURL, cache.NewRedisCacheAdapter(redisClient))
552554
mcpmetadata.Attach(mux, mcpMetadataService)
553-
mcp.Attach(mux, mcp.NewService(logger, tracerProvider, meterProvider, db, sessionManager, env, posthogClient, serverURL, encryptionClient, cache.NewRedisCacheAdapter(redisClient), guardianPolicy, functionsOrchestrator, oauthService, billingTracker, billingRepo, tcm), mcpMetadataService)
555+
mcp.Attach(mux, mcp.NewService(logger, tracerProvider, meterProvider, db, sessionManager, env, posthogClient, serverURL, encryptionClient, cache.NewRedisCacheAdapter(redisClient), guardianPolicy, functionsOrchestrator, oauthService, billingTracker, billingRepo, tcm, ragService), mcpMetadataService)
554556
chat.Attach(mux, chat.NewService(logger, db, sessionManager, openRouter))
555557
if slackClient.Enabled() {
556558
slack.Attach(mux, slack.NewService(logger, db, sessionManager, encryptionClient, redisClient, slackClient, temporalClient, slack.Configurations{

server/database/sqlc.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ overrides:
5454
go_type:
5555
import: github.com/speakeasy-api/gram/server/internal/urn
5656
type: Tool
57+
- db_type: "vector"
58+
go_type:
59+
import: github.com/pgvector/pgvector-go
60+
type: Vector
5761

5862
sql:
5963
- schema: schema.sql
@@ -341,3 +345,13 @@ sql:
341345
out: "../internal/resources/repo"
342346
sql_package: "pgx/v5"
343347
omit_unused_structs: true
348+
349+
- schema: schema.sql
350+
queries: ../internal/rag/repo/queries.sql
351+
engine: postgresql
352+
gen:
353+
go:
354+
package: "repo"
355+
out: "../internal/rag/repo"
356+
sql_package: "pgx/v5"
357+
omit_unused_structs: true

server/design/shared/toolset.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ var Toolset = Type("Toolset", func() {
5050
Attribute("function_environment_variables", ArrayOf(FunctionEnvironmentVariable), "The function environment variables that are relevant to the toolset")
5151
Attribute("tools", ArrayOf(Tool), "The tools in this toolset")
5252
Attribute("tool_urns", ArrayOf(String), "The tool URNs in this toolset")
53+
Attribute("toolset_version", Int64, "The version of the toolset (will be 0 if none exists)")
5354
Attribute("resources", ArrayOf(Resource), "The resources in this toolset")
5455
Attribute("resource_urns", ArrayOf(String), "The resource URNs in this toolset")
5556

@@ -68,7 +69,7 @@ var Toolset = Type("Toolset", func() {
6869
Description("When the toolset was last updated.")
6970
Format(FormatDateTime)
7071
})
71-
Required("id", "project_id", "organization_id", "account_type", "name", "slug", "tools", "prompt_templates", "tool_urns", "resources", "resource_urns", "created_at", "updated_at")
72+
Required("id", "project_id", "organization_id", "account_type", "name", "slug", "tools", "toolset_version", "prompt_templates", "tool_urns", "resources", "resource_urns", "created_at", "updated_at")
7273
})
7374

7475
var ToolsetEntry = Type("ToolsetEntry", func() {

server/gen/http/cli/gram/cli.go

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/gen/http/openapi.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)