2024年最新GolangLangChain与向量数据库集成完全指南:聊天机器人实例

云信安装大师
90
AI 质量分
3 5 月, 2025
4 分钟阅读
0 阅读

2024年最新GolangLangChain与向量数据库集成完全指南:聊天机器人实例

引言

在AI技术快速发展的2024年,构建智能聊天机器人已成为企业提升客户服务效率的重要手段。本文将带你使用Golang版本的LangChain框架与向量数据库集成,从零开始构建一个能理解自然语言并给出智能回复的聊天机器人。

准备工作

环境要求

  • Go 1.21+ (推荐使用最新稳定版)
  • PostgreSQL 15+ (作为向量数据库)
  • pgvector扩展 (用于向量存储)
  • OpenAI API密钥 (或其他LLM提供商)

安装依赖

代码片段
# 安装Go依赖
go get github.com/tmc/langchaingo
go get github.com/jackc/pgx/v5
go get github.com/pgvector/pgvector-go

项目结构

代码片段
/chatbot
├── main.go          # 主程序入口
├── database         # 数据库相关代码
│   ├── setup.go     # 数据库初始化
│   └── store.go     # 向量存储实现
├── chain            # LangChain相关代码
│   ├── memory.go    # 对话记忆管理
│   └── prompt.go    # 提示词模板
└── config           # 配置管理
    └── config.go    # API密钥等配置

详细步骤

1. 配置向量数据库

首先我们需要设置PostgreSQL并启用pgvector扩展:

代码片段
-- 创建数据库和扩展(以管理员身份执行)
CREATE DATABASE chatbot_db;
\c chatbot_db;
CREATE EXTENSION IF NOT EXISTS vector;

-- 创建存储聊天记录的表格(在应用中使用)
CREATE TABLE chat_messages (
    id SERIAL PRIMARY KEY,
    session_id TEXT NOT NULL,
    message_text TEXT NOT NULL,
    embedding vector(1536), -- OpenAI嵌入维度为1536
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    metadata JSONB
);

2. Go项目初始化

config/config.go – 配置文件示例:

代码片段
package config

type Config struct {
    DatabaseURL string `env:"DATABASE_URL,required"`
    OpenAIKey   string `env:"OPENAI_API_KEY,required"`
}

func Load() (*Config, error) {
    var cfg Config

    // 实际项目中推荐使用github.com/caarlos0/env等库加载环境变量
    cfg.DatabaseURL = "postgres://user:password@localhost:5432/chatbot_db"
    cfg.OpenAIKey = "your-openai-key"

    return &cfg, nil
}

3. LangChain集成实现

chain/prompt.go – 定义对话模板:

代码片段
package chain

import (
    "github.com/tmc/langchaingo/llms/openai"
    "github.com/tmc/langchaingo/prompts"
)

func NewChatPromptTemplate() prompts.ChatPromptTemplate {
    return prompts.ChatPromptTemplate{
        Messages: []prompts.MessageFormatter{
            prompts.NewSystemMessagePromptTemplate(
                "你是一个乐于助人的AI助手,专门回答关于技术问题的咨询。",
                nil,
            ),
            prompts.NewHumanMessagePromptTemplate(
                "{{.input}}",
                []string{"input"},
            ),
        },
    }
}

func NewLLM() (*openai.Chat, error) {
    return openai.NewChat(openai.WithModel("gpt-4"))
}

4. 向量存储实现

database/store.go – PostgreSQL向量存储:

代码片段
package database

import (
    "context"
    "fmt"

    "github.com/jackc/pgx/v5/pgxpool"
    "github.com/pgvector/pgvector-go"
)

type VectorStore struct {
    db *pgxpool.Pool
}

func NewVectorStore(db *pgxpool.Pool) *VectorStore {
    return &VectorStore{db: db}
}

// StoreEmbedding 存储文本及其向量表示到数据库
func (vs *VectorStore) StoreEmbedding(ctx context.Context, sessionID, text string, embedding []float32) error {
    vector := pgvector.NewVector(embedding)

    sql := `INSERT INTO chat_messages 
            (session_id, message_text, embedding) 
            VALUES ($1, $2, $3)`

    _, err := vs.db.Exec(ctx, sql, sessionID, text, vector)
    return err
}

// FindSimilarTexts 查找语义相似的对话历史记录(用于上下文记忆)
func (vs *VectorStore) FindSimilarTexts(ctx context.Context, embedding []float32, limit int) ([]string, error) {
    vector := pgvector.NewVector(embedding)

    sql := `SELECT message_text FROM chat_messages 
            ORDER BY embedding <-> $1 
            LIMIT $2`

    rows, err := vs.db.Query(ctx, sql, vector, limit)
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    var results []string

    for rows.Next() {
        var text string
        if err := rows.Scan(&text); err != nil {
            return nil, err 
        }

        if text != "" {
            results = append(results, text)
        }
    }

    return results, nil 
}

5. Main函数整合所有组件

main.go – Chatbot主程序:

代码片段
package main

import (
    "context"
    "fmt"

    c "chatbot/config"
    db "chatbot/database"
    l "chatbot/chain"

    "github.com/jackc/pgx/v5/pgxpool"
)

func main() {
    fmt.Println("启动聊天机器人服务...")

    // 加载配置 
    cfg := c.Load()

    // 初始化数据库连接池 
    dbPool := db.InitDB(cfg.DatabaseURL)
    defer dbPool.Close()

    vectorStore := db.NewVectorStore(dbPool)

    for { // REPL循环 
        fmt.Print("\n用户输入: ")
        var input string

        if _, err := fmt.Scanln(&input); err != nil || input == "exit" {  
            break  
        }

        // TODO: 
        // - [ ] Step1: Embed用户输入文本  
        // - [ ] Step2: Query相似历史消息作为上下文  
        // - [ ] Step3: Build prompt with context  
        // - [ ] Step4: Call LLM生成回复  
        // - [ ] Step5: Store conversation history  

        fmt.Printf("AI回复: %s\n", "TODO")
    }

    fmt.Println("\n退出聊天机器人服务")
}

LLM集成与对话逻辑完善

让我们完成main.go中的TODO部分:

代码片段
// ...前面的代码保持不变...

for { // REPL循环 
    fmt.Print("\n用户输入: ")
    var input string

    if _, err := fmt.Scanln(&input); err != nil || input == "exit" {  
        break  
    }

    // Step1: Embed用户输入文本 (简化版,实际应调用OpenAI Embedding API)
    inputEmbedding := make([]float32,1536) // TODO替换为真实嵌入

    // Step2: Query相似历史消息作为上下文  
    if contexts ,err:= vectorStore.FindSimilarTexts(context.Background(), inputEmbedding ,3);err==nil{
        fmt.Printf("[DEBUG] Found %d relevant contexts\n", len(contexts))
        for _,ctx:=range contexts{
            fmt.Printf("- %s\n",ctx)
        }
        input=fmt.Sprintf("Context:\n%s\n\nQuestion:%s",strings.Join(contexts,"\n"),input)
    }

    // Step3&4: Build prompt and call LLM  
    prompt:=l.NewChatPromptTemplate()
    messages,_:=prompt.FormatMessages(map[string]any{"input":input})

    if llm ,err:=l.NewLLM();err==nil{
        resp ,err:=llm.Call(context.Background(),messages)
        if err!=nil{
            fmt.Printf("Error calling LLM:%v\n",err )
            continue 
        }

        fmt.Printf("AI回复:%s\n",resp.Content )

        // Step5: Store conversation history  
        if err:=vectorStore.StoreEmbedding(context.Background(),"default_session",input,inputEmbedding);err!=nil{
            fmt.Printf("Warning:failed to store message:%v\n",err )
        }
        if err:=vectorStore.StoreEmbedding(context.Background(),"default_session",resp.Content,inputEmbedding);err!=nil{
            fmt.Printf("Warning:failed to store response:%v\n",err )
        }
    }else{
        fmt.Printf("Error initializing LLM:%v\n",err )
    }
}

// ...后续代码...

GPT嵌入API集成补充

为了完整实现,我们需要添加真正的文本嵌入功能。在chain/embedding.go中添加:

代码片段
package chain 

import (
    gptembedder "github.com/tmc/langchaingo/embeddings/openai"
)

type Embedder struct {
    gpt *gptembedder.EmbedderImplV2 
}

func NewEmbedder(apiKey string) (*Embedder ,error){
    e ,err:= gptembedder.NewOpenAI(
       gptembedder.WithToken(apiKey),
       gptembedder.WithModel("text-embedding-3-small"),
       gptembedder.WithBatchSize(5), 
       )
    if err!=nil{return nil ,err} 
    return &Embedder{gpt:e},nil 
}

func(e*Embedder )GetTextEmbedding(text string)([]float32 ,error){
    return e.gpt.EmbedQuery(context.Background(),text )
} 

//然后在main中初始化:
embedder,_:=chain.NewEmbedder(cfg.OpenAIKey ) 

//替换之前的假嵌入:
inputEmbeding,_:=embedder.GetTextEmbedding(input ) 

QA测试示例

让我们测试几个常见问题:

代码片段
启动聊天机器人服务...

用户输入: Golang中如何连接PostgreSQL?
[DEBUG] Found relevant contexts...
AI回复:在Go中连接PostgreSQL可以使用pgx驱动。基本步骤如下:

1.安装驱动:
   go get github.com/jackc/pgx/v5  

2.创建连接池:
   poolConfig,_:=pgxpool.ParseConfig("postgres://user:pwd@localhost/db")   
   pool,_:=pgxpool.NewWithConfig(ctx ,poolConfig )

3.执行查询:
   row:=pool.QueryRow(ctx,"SELECT version()")  

需要更详细的示例吗?

用户输入:LangChain是什么?
[DEBUG] Found relevant contexts...
AI回复:LangChain是一个用于构建基于大语言模型应用的框架。它提供:

1.标准化接口连接不同LLM(如OpenAI、Anthropic等)

2.组件化设计包含:
   - Prompt模板管理   
   - Memory记忆管理   
   - Chains链式调用   

3.Golang版本(langchaingo)是官方支持的Go实现。

您想了解具体哪个方面的功能呢?

exit  

退出聊天机器人服务  

注意事项

1.性能优化
– pgvector索引优化:对大型数据集创建IVFFlat索引加速搜索:

代码片段
CREATE INDEX ON chat_messages USING ivfflat (embedding vector_cosine_ops) WITH (lists =100);
  • Go连接池调优:根据负载调整MaxConns参数

2.安全考虑
– SQL注入防护:始终使用参数化查询($1,$2等格式)
– API密钥管理:不要硬编码在源码中,使用环境变量或密钥管理服务

3.生产环境增强
会话隔离:为每个用户/会话维护独立的session_id
限流控制:防止API滥用
缓存层:对常见查询结果添加Redis缓存

总结

通过本教程,我们完成了以下关键步骤:

搭建基础架构:PostgreSQL+pgvector作为向量存储后端
LangChain集成:利用其标准接口管理LLM交互流程
上下文记忆:通过相似度检索实现对话连贯性
端到端测试:验证了问答系统的核心功能

进阶方向建议
1.多模态扩展:支持图片/PDF等非结构化数据解析
2.微调部署:针对垂直领域微调开源模型降低成本
3.评估体系:添加自动化测试评估回答质量

完整项目代码可参考GitHub仓库:示例仓库链接

希望这篇指南能帮助你快速上手基于Golang的智能对话系统开发!遇到问题欢迎在评论区讨论。

原创 高质量