aster 默认采用 文件 + grep 的方式实现长期记忆, 对很多场景(用户/项目/资源级记忆)已经足够简单可靠。但对于部分用户, 仍然希望接入向量数据库/语义检索(RAG)。
本示例展示如何在保持核心运行时轻量的前提下, 通过 可插拔 VectorStore + Embedder 增强语义记忆能力。
注意: 当前版本仅提供内存 VectorStore 和 MockEmbedder 作为示例实现, 方便你理解接口与集成方式。生产环境需自行实现适配器, 对接真实的向量数据库和 embedding 服务。
下面的组件可以直接调用 aster serve 暴露的 /v1/memory/semantic/search 接口, 体验语义检索效果:
向量相关抽象定义在 pkg/vector 中:
// pkg/vector/store.go
type Document struct {
ID string
Text string
Embedding []float32
Metadata map[string]interface{}
Namespace string
}
type Query struct {
Vector []float32
TopK int
Namespace string
Filter map[string]interface{}
}
type Hit struct {
ID string
Score float64
Metadata map[string]interface{}
}
type VectorStore interface {
Upsert(ctx context.Context, docs []Document) error
Delete(ctx context.Context, ids []string) error
Query(ctx context.Context, q Query) ([]Hit, error)
Close() error
}
// pkg/vector/embedder.go
type Embedder interface {
EmbedText(ctx context.Context, texts []string) ([][]float32, error)
}
语义记忆组件定义在 pkg/memory/semantic.go:
type SemanticMemoryConfig struct {
Store vector.VectorStore
Embedder vector.Embedder
NamespaceScope string // "user" | "project" | "resource" | "global"
TopK int
}
type SemanticMemory struct {
cfg SemanticMemoryConfig
}
func NewSemanticMemory(cfg SemanticMemoryConfig) *SemanticMemory
func (sm *SemanticMemory) Enabled() bool
func (sm *SemanticMemory) Close() error
// Index 将文本写入向量索引
func (sm *SemanticMemory) Index(ctx context.Context, docID, text string, meta map[string]interface{}) error
// Search 基于自然语言查询 + 元数据执行向量检索
func (sm *SemanticMemory) Search(ctx context.Context, query string, meta map[string]interface{}, topK int) ([]vector.Hit, error)
示例代码: examples/memory-semantic/main.go
ctx := context.Background()
// 1. 创建向量存储和 embedder
store := vector.NewMemoryStore()
embedder := vector.NewMockEmbedder(16)
// 2. 创建语义记忆组件
semMem := memory.NewSemanticMemory(memory.SemanticMemoryConfig{
Store: store,
Embedder: embedder,
NamespaceScope: "resource",
TopK: 3,
})
// 3. 索引几段示例文本
docs := []struct {
id string
text string
meta map[string]interface{}
}{
{
id: "doc-1",
text: "Paris is the capital of France.",
meta: map[string]interface{}{"user_id": "alice", "resource_id": "europe-notes"},
},
{
id: "doc-2",
text: "Berlin is the capital of Germany.",
meta: map[string]interface{}{"user_id": "alice", "resource_id": "europe-notes"},
},
}
for _, d := range docs {
if err := semMem.Index(ctx, d.id, d.text, d.meta); err != nil {
panic(err)
}
}
// 4. 在 Alice 的 europe-notes 命名空间内进行语义检索
query := "What is the capital of France?"
meta := map[string]interface{}{"user_id": "alice", "resource_id": "europe-notes"}
hits, err := semMem.Search(ctx, query, meta, 3)
if err != nil {
panic(err)
}
fmt.Println("Semantic search hits:", hits)
运行:
cd examples
go run ./memory-semantic
你会看到 doc-1 得分较高, 表明语义检索可以在指定命名空间内找到相关文档。
pkg/tools/builtin/semantic_memory.go 提供了一个内置工具 semantic_search, 你可以在构建 Agent 时按需注册:
semMem := memory.NewSemanticMemory(...)
toolRegistry := tools.NewRegistry()
builtin.RegisterAll(toolRegistry)
if semMem.Enabled() {
toolRegistry.Register("semantic_search", func(cfg map[string]interface{}) (tools.Tool, error) {
return builtin.NewSemanticSearchTool(semMem), nil
})
}
工具输入:
{
"query": "自然语言查询文本",
"top_k": 5,
"metadata": {
"user_id": "alice",
"project_id": "demo"
}
}
输出为命中列表:
[
{"id": "doc-1", "score": 0.87, "metadata": {...}},
{"id": "doc-2", "score": 0.75, "metadata": {...}}
]
这样 Agent 在工具列表中就可以选择使用 semantic_search 进行 RAG 检索, 而无需修改核心运行时。
在 aster.yaml 中可以声明向量存储、embedder 和语义记忆配置:
vector_stores:
- name: main
kind: memory # 内存向量存储, 适合本地测试/示例
embedders:
- name: default
kind: mock # mock 实现, 生产环境应替换为真实 embedder
semantic_memory:
enabled: true
store: main
embedder: default
top_k: 8
namespace_scope: resource
当你使用 CLI 启动 Server 时:
aster serve \
--addr :8080 \
--workspace ./workspace \
--store .aster \
--config ./aster.yaml
aster serve 会自动:
VectorStore(当前为 MemoryStore) 和 Embedder(当前为 MockEmbedder);SemanticMemory;semantic_search 工具。如果配置无效或未提供有效 store/embedder, 语义记忆会被跳过, 不影响现有行为。
如果你已经在 PostgreSQL 中安装了 pgvector 扩展, 并希望使用 OpenAI 的 embedding 模型, 可以在 aster.yaml 中这样配置:
vector_stores:
- name: main
kind: pgvector
dsn: postgres://user:password@localhost:5432/aster?sslmode=disable
table: agent_vectors
metric: cosine
dimension: 1536
embedders:
- name: default
kind: openai
model: text-embedding-3-small
env_api_key: OPENAI_API_KEY
semantic_memory:
enabled: true
store: main
embedder: default
top_k: 8
namespace_scope: resource
在数据库中确保创建好表结构(示例):
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE IF NOT EXISTS agent_vectors (
id TEXT PRIMARY KEY,
namespace TEXT,
embedding VECTOR(1536),
metadata JSONB
);
启动服务前设置环境变量:
export OPENAI_API_KEY=sk-...
aster serve --config ./aster.yaml
此时 semantic_search 工具会使用 pgvector 存储向量, 使用 OpenAI embeddings 进行查询。
SemanticMemory。推荐下一步:
vector.VectorStore adapter 对接现有向量数据库(PgVector/LibSQL/Qdrant等)。vector.Embedder adapter 对接 OpenAI/本地 embedding 服务。aster.yaml 中添加相应的 kind 和连接参数。