您可以使用 PostgreSQL 和 pgvector
做為擷取器實作項目。使用
把它當做起點,然後進行修改,使其與資料庫搭配運作
結構定義。
我們使用 database/sql 連線至 Postgres 伺服器,但您仍可選擇使用其他用戶端程式庫。
func defineRetriever(db *sql.DB, embedder ai.Embedder) ai.Retriever {
f := func(ctx context.Context, req *ai.RetrieverRequest) (*ai.RetrieverResponse, error) {
eres, err := ai.Embed(ctx, embedder, ai.WithEmbedDocs(req.Document))
if err != nil {
return nil, err
}
rows, err := db.QueryContext(ctx, `
SELECT episode_id, season_number, chunk as content
FROM embeddings
WHERE show_id = $1
ORDER BY embedding <#> $2
LIMIT 2`,
req.Options, pgv.NewVector(eres.Embeddings[0].Embedding))
if err != nil {
return nil, err
}
defer rows.Close()
res := &ai.RetrieverResponse{}
for rows.Next() {
var eid, sn int
var content string
if err := rows.Scan(&eid, &sn, &content); err != nil {
return nil, err
}
meta := map[string]any{
"episode_id": eid,
"season_number": sn,
}
doc := &ai.Document{
Content: []*ai.Part{ai.NewTextPart(content)},
Metadata: meta,
}
res.Documents = append(res.Documents, doc)
}
if err := rows.Err(); err != nil {
return nil, err
}
return res, nil
}
return ai.DefineRetriever(provider, "shows", f)
}
以下是在流程中使用擷取器的方法:
retriever := defineRetriever(db, embedder)
type input struct {
Question string
Show string
}
genkit.DefineFlow("askQuestion", func(ctx context.Context, in input) (string, error) {
res, err := ai.Retrieve(ctx, retriever,
ai.WithRetrieverOpts(in.Show),
ai.WithRetrieverText(in.Question))
if err != nil {
return "", err
}
for _, doc := range res.Documents {
fmt.Printf("%+v %q\n", doc.Metadata, doc.Content[0].Text)
}
// Use documents in RAG prompts.
return "", nil
})