使用deepseek快速构建你的知识库

562 阅读4分钟

使用ollama快速本地集成deepseek并构建你的知识库

前置条件

ollama

安装地址:github.com/ollama/olla… 安装完成后可以通过ollama run model启动相应模型,如下常用模型

模型参数大小运行命令
DeepSeek-R17B4.7GBollama run deepseek-r1
DeepSeek-R1671B404GBollama run deepseek-r1:671b
Llama 3.370B43GBollama run llama3.3
Llama 3.23B2.0GBollama run llama3.2
Llama 3.21B1.3GBollama run llama3.2:1b
Llama 3.2 Vision11B7.9GBollama run llama3.2-vision

具体的模型列表可参见:ollama.com/library

docker

安装地址:www.docker.com/get-started…

image.png

知识库构建

环境准备

这里我们使用mongo存储员工薪资数据,调用ollama实现问答 使用dokcer启动一个mongo容器

docker run -d --name mongo \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=admin \
-p 27017:27017 \
mongo

使用ollama运行deepseek-r1,本地部署会占用端口11434

ollama run deepseek-r1:7b

模拟数据

生成相应的json数据,存储在文件中,在init中将文件写入mongo

✅ MongoDB 连接成功!
✅ JSON 数据已生成!
✅ employees 集合已清空
✅ 员工数据已成功写入 MongoDB!

查询数据

查询数据并且按切片返回

func queryEmployees() ([]string, error) {
    collection := mongoClient.Database("company").Collection("employees")

    // 查询所有员工
    cursor, err := collection.Find(context.TODO(), bson.M{})
    if err != nil {
       return nil, fmt.Errorf("查询 MongoDB 失败: %v", err)
    }
    defer cursor.Close(context.TODO())

    var results []string

    for cursor.Next(context.TODO()) {
       var emp Employee
       if err := cursor.Decode(&emp); err != nil {
          return nil, fmt.Errorf("解码失败: %v", err)
       }

       // 格式化员工信息为字符串
       empStr := fmt.Sprintf("ID: %d, 姓名: %s, 年龄: %d, 性别: %s, 薪资: %.2f",
          emp.ID, emp.Name, emp.Age, emp.Gender, emp.Salary)
       results = append(results, empStr)
    }

    // 检查游标错误
    if err := cursor.Err(); err != nil {
       return nil, fmt.Errorf("遍历游标失败: %v", err)
    }

    return results, nil
}

调用模型回答问题

    func TestLocalDeepSeek(t *testing.T) {
        // 查询 MongoDB 中的数据
        data, err := queryEmployees()
        if err != nil {
           log.Fatal("查询 MongoDB 失败:", err)
        }
        //构建消息
        messages := []llms.MessageContent{}
        messages = append(messages, llms.MessageContent{
           Role:  llms.ChatMessageTypeSystem,
           Parts: []llms.ContentPart{llms.TextContent{backGround}},
        })

        for _, s := range data {
           messages = append(messages, llms.MessageContent{
              Role:  llms.ChatMessageTypeSystem,
              Parts: []llms.ContentPart{llms.TextContent{s}},
           })
        }
        question := "20-30岁员工中,薪资最高和最低的分别是谁?"
        messages = append(messages, llms.MessageContent{
           Role:  llms.ChatMessageTypeHuman,
           Parts: []llms.ContentPart{llms.TextContent{question}},
        })
        ctx := context.Background()
        answer, err := deepSeek.GenerateContent(ctx, messages)
        if err != nil {
           log.Fatal("deepseek err:", err)
        }
        choices := answer.Choices
        for i := 0; i < len(choices); i++ {
           log.Fatal(choices[i].Content)
        }
    }

效果如下,根据查询的内容,给出了正确的答案 image.png

完整代码

package deepseek

import (
    "context"
    "encoding/json"
    "fmt"
    "github.com/tmc/langchaingo/llms"
    "github.com/tmc/langchaingo/llms/ollama"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "log"
    "os"
    "testing"
)

// Employee 结构体
type Employee struct {
    ID     int     `json:"id" bson:"id"`
    Name   string  `json:"name" bson:"name"`
    Age    int     `json:"age" bson:"age"`
    Gender string  `json:"gender" bson:"gender"`
    Salary float64 `json:"salary" bson:"salary"`
}

var mongoClient *mongo.Client

var deepSeek *ollama.LLM

var backGround = "你是一个ai助手, 请根据给定的内容回答问题, 直接给出最终的答案,不要给出思考过程"

// init 初始化 MongoDB deepseek
func init() {
    var err error
    mongoURI := "mongodb://admin:admin@localhost:27017/?authSource=admin" //docker启动时设置用户密码

    clientOptions := options.Client().ApplyURI(mongoURI)

    // 连接 MongoDB
    mongoClient, err = mongo.Connect(context.TODO(), clientOptions)
    if err != nil {
       log.Fatal("MongoDB 连接失败:", err)
    }

    // 检查连接
    err = mongoClient.Ping(context.TODO(), nil)
    if err != nil {
       log.Fatal("无法连接到 MongoDB:", err)
    }
    fmt.Println("✅ MongoDB 连接成功!")

    err = mockData()
    if err != nil {
       log.Fatal("写入 MongoDB 失败:", err)
    }

    model := "deepseek-r1:7b"
    deepSeekUrl := "http://127.0.0.1:11434"
    deepSeek, err = ollama.New(ollama.WithModel(model), ollama.WithServerURL(deepSeekUrl))
    if err != nil {
       log.Fatal("初始化DeepSeek失败:", err)
    }
    _, err = deepSeek.CreateEmbedding(context.Background(), []string{backGround})
    if err != nil {
       log.Fatal("无法连接DeepSeek:", err)
    }
    fmt.Println("✅ DeepSeek 初始化连接成功!")
}

// generateJSON 生成 JSON 数据并保存到文件
func generateJSON(filename string) error {
    employees := []Employee{
       {ID: 1, Name: "Alice", Age: 30, Gender: "Female", Salary: 80000},
       {ID: 2, Name: "Bob", Age: 35, Gender: "Male", Salary: 90000},
       {ID: 3, Name: "Charlie", Age: 40, Gender: "Male", Salary: 100000},
       {ID: 4, Name: "Diana", Age: 28, Gender: "Female", Salary: 75000},
       {ID: 5, Name: "Ethan", Age: 32, Gender: "Male", Salary: 85000},
       {ID: 6, Name: "Jhon", Age: 27, Gender: "Male", Salary: 12000},
       {ID: 7, Name: "Mike", Age: 21, Gender: "Male", Salary: 5000},
       {ID: 8, Name: "Heinz", Age: 28, Gender: "Male", Salary: 100000},
       {ID: 9, Name: "Adolf", Age: 27, Gender: "Male", Salary: 88000},
       {ID: 10, Name: "Rudolf", Age: 26, Gender: "Male", Salary: 89000},
    }

    // 转换为 JSON 并写入文件
    data, err := json.MarshalIndent(employees, "", "  ")
    if err != nil {
       return err
    }

    return os.WriteFile(filename, data, 0644)
}

// readAndInsertToMongo 读取 JSON 并插入 MongoDB
func readAndInsertToMongo(filename string) error {
    // 读取 JSON 文件
    data, err := os.ReadFile(filename)
    if err != nil {
       return err
    }

    var employees []Employee
    err = json.Unmarshal(data, &employees)
    if err != nil {
       return err
    }

    // 选择数据库和集合
    collection := mongoClient.Database("company").Collection("employees")

    // 清空 employees 集合
    _, err = collection.DeleteMany(context.TODO(), bson.M{})
    if err != nil {
       return fmt.Errorf("清空 employees 失败: %v", err)
    }

    fmt.Println("✅ employees 集合已清空")

    // 将数据插入 MongoDB
    var docs []interface{}
    for _, emp := range employees {
       docs = append(docs, emp)
    }

    _, err = collection.InsertMany(context.TODO(), docs)
    if err != nil {
       return err
    }

    fmt.Println("✅ 员工数据已成功写入 MongoDB!")
    return nil
}

// mockData 写入数据
func mockData() error {
    jsonFile := "employees.json"

    // 生成 JSON 数据
    err := generateJSON(jsonFile)
    if err != nil {
       log.Fatal("生成 JSON 失败:", err)
    }
    fmt.Println("✅ JSON 数据已生成!")

    // 读取 JSON 并写入 MongoDB
    err = readAndInsertToMongo(jsonFile)
    if err != nil {
       log.Fatal("写入 MongoDB 失败:", err)
    }
    return err
}

// queryEmployees 查询 MongoDB 中的员工数据
func queryEmployees() ([]string, error) {
    collection := mongoClient.Database("company").Collection("employees")

    // 查询所有员工
    cursor, err := collection.Find(context.TODO(), bson.M{})
    if err != nil {
       return nil, fmt.Errorf("查询 MongoDB 失败: %v", err)
    }
    defer cursor.Close(context.TODO())

    var results []string

    for cursor.Next(context.TODO()) {
       var emp Employee
       if err := cursor.Decode(&emp); err != nil {
          return nil, fmt.Errorf("解码失败: %v", err)
       }

       // 格式化员工信息为字符串
       empStr := fmt.Sprintf("ID: %d, 姓名: %s, 年龄: %d, 性别: %s, 薪资: %.2f",
          emp.ID, emp.Name, emp.Age, emp.Gender, emp.Salary)
       results = append(results, empStr)
    }

    // 检查游标错误
    if err := cursor.Err(); err != nil {
       return nil, fmt.Errorf("遍历游标失败: %v", err)
    }

    return results, nil
}

func TestLocalDeepSeek(t *testing.T) {
    // 查询 MongoDB 中的数据
    data, err := queryEmployees()
    if err != nil {
       log.Fatal("查询 MongoDB 失败:", err)
    }
    //构建消息
    messages := []llms.MessageContent{}
    messages = append(messages, llms.MessageContent{
       Role:  llms.ChatMessageTypeSystem,
       Parts: []llms.ContentPart{llms.TextContent{backGround}},
    })

    for _, s := range data {
       messages = append(messages, llms.MessageContent{
          Role:  llms.ChatMessageTypeSystem,
          Parts: []llms.ContentPart{llms.TextContent{s}},
       })
    }
    question := "20-30岁员工中,薪资最高和最低的分别是谁?"
    messages = append(messages, llms.MessageContent{
       Role:  llms.ChatMessageTypeHuman,
       Parts: []llms.ContentPart{llms.TextContent{question}},
    })
    ctx := context.Background()
    answer, err := deepSeek.GenerateContent(ctx, messages)
    if err != nil {
       log.Fatal("deepseek err:", err)
    }
    choices := answer.Choices
    for i := 0; i < len(choices); i++ {
       log.Fatal(choices[i].Content)
    }
}