Go项目实战:使用Ollama本地部署大模型实现AI智能笔记生成

Go项目实战:使用Ollama本地部署大模型实现AI智能笔记生成

前言

在当今AI技术快速发展的背景下,越来越多的应用开始集成大语言模型(LLM)能力。然而,依赖云端API不仅成本高昂,还存在数据隐私和网络延迟等问题。本文将分享一个实际项目经验------如何在Go后端项目中集成Ollama,实现本地大模型部署,用于课程音视频的智能笔记生成。

项目背景

本项目是一个"通用音视频智能学习辅助平台",核心功能是:

  • 教师上传课程视频
  • 系统自动提取音频
  • 学生点击"解析"后,AI自动生成结构化笔记

技术栈:

  • 后端:Go + Gin + GORM
  • 存储:MySQL + MinIO
  • AI:Ollama(本地大模型)+ Whisper(语音识别)

为什么选择本地部署?

1. 成本控制

云端API(如OpenAI)按token计费,对于教育场景的大量视频解析,成本会迅速累积。本地部署后,只需要承担硬件成本。

2. 离线可用

不依赖网络连接,在内网环境也能正常使用。

3. 可定制性

可以根据需求选择不同规模的模型,平衡性能和资源消耗。

Ollama简介

Ollama是一个轻量级的本地大模型运行工具,支持:

  • 一键安装和运行主流开源模型(Llama、Qwen、Mistral等)
  • 兼容OpenAI API格式
  • 自动管理模型下载和版本
  • 支持GPU/CPU推理

实现方案

1. 架构设计

复制代码
┌─────────────────────────────────────────────────────────┐
│                    Go Backend (Gin)                      │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  ┌──────────────┐    ┌──────────────┐    ┌────────────┐ │
│  │   AI Service │───▶│  LLM Client  │───▶│   Ollama   │ │
│  └──────────────┘    └──────────────┘    │  localhost  │ │
│         │                                 │   :11434    │ │
│         │                                 └────────────┘ │
│         ▼                                                │
│  ┌──────────────┐                                       │
│  │Prompt Manager│                                       │
│  └──────────────┘                                       │
└─────────────────────────────────────────────────────────┘

2. 核心代码实现

LLM客户端封装
go 复制代码
package ai

import (
    "bytes"
    "context"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "strings"
)

type LLMClient struct {
    client   *http.Client
    model    string
    provider string  // "ollama" 或 "openai"
    baseURL  string
}

func NewLLMClient(apiKey, baseURL, model string) *LLMClient {
    provider := "openai"
    // 自动检测是否为Ollama
    if strings.Contains(baseURL, "localhost:11434") ||
       strings.Contains(baseURL, "127.0.0.1:11434") {
        provider = "ollama"
    }

    return &LLMClient{
        client:   &http.Client{Timeout: 5 * time.Minute},
        model:    model,
        provider: provider,
        baseURL:  baseURL,
    }
}
Ollama调用实现
go 复制代码
func (c *LLMClient) generateWithOllama(
    ctx context.Context,
    systemRole, prompt string,
    mutateOptions func(map[string]any),
) (string, error) {
    base := c.baseURL
    if base == "" {
        base = "http://localhost:11434"
    }
    url := strings.TrimRight(base, "/") + "/api/chat"

    // 构建请求体
    body := map[string]any{
        "model": c.model,
        "messages": []map[string]string{
            {"role": "system", "content": systemRole},
            {"role": "user", "content": prompt},
        },
        "stream": false,
    }

    // 支持动态调整参数
    options := map[string]any{}
    if v := os.Getenv("OLLAMA_NUM_CTX"); v != "" {
        options["num_ctx"], _ = strconv.Atoi(v)
    }
    if mutateOptions != nil {
        mutateOptions(options)
    }
    if len(options) > 0 {
        body["options"] = options
    }

    // 发送请求
    b, _ := json.Marshal(body)
    req, _ := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(b))
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.client.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    var result struct {
        Message struct {
            Content string `json:"content"`
        } `json:"message"`
    }
    json.NewDecoder(resp.Body).Decode(&result)
    return result.Message.Content, nil
}
智能降级策略

本地部署的一大挑战是资源限制。我们实现了多级降级策略:

go 复制代码
func (c *LLMClient) GenerateContent(ctx context.Context, systemRole, prompt string) (string, error) {
    if c.provider == "ollama" {
        // 第一次尝试:完整配置
        content, err := c.generateWithOllama(ctx, systemRole, prompt, nil)
        if !isOllamaRunnerCrash(err) {
            return content, err
        }

        // 第二次尝试:缩小上下文窗口
        time.Sleep(2 * time.Second)
        content, err = c.generateWithOllama(ctx, systemRole, prompt, func(opts map[string]any) {
            opts["num_ctx"] = 2048
            opts["num_predict"] = 512
        })
        if !isOllamaRunnerCrash(err) {
            return content, err
        }

        // 第三次尝试:禁用GPU,使用CPU推理
        time.Sleep(3 * time.Second)
        return c.generateWithOllama(ctx, systemRole, prompt, func(opts map[string]any) {
            opts["num_ctx"] = 1024
            opts["num_predict"] = 256
            opts["num_gpu"] = 0  // 禁用GPU层
        })
    }
    // ... OpenAI API调用
}

3. 环境变量配置

bash 复制代码
# AI配置
AI_LLM_PROVIDER=ollama
AI_LLM_BASE_URL=http://localhost:11434
AI_MODEL=qwen2.5:7b

# Ollama参数调优
OLLAMA_NUM_CTX=4096        # 上下文窗口大小
OLLAMA_NUM_PREDICT=2048    # 最大生成token数
OLLAMA_TEMPERATURE=0.7     # 温度参数
OLLAMA_NUM_GPU=1           # GPU层数(0禁用GPU)

4. Prompt管理

针对不同学科,我们设计了差异化的Prompt模板:

go 复制代码
type PromptManager struct {
    defaults map[string]string
}

func NewPromptManager() *PromptManager {
    return &PromptManager{
        defaults: map[string]string{
            "system": `你是一个专业的课程学习助手。请根据以下音频转录内容,
                       生成结构化的学习笔记。要求:
                       1. 提取核心知识点
                       2. 标注重点和难点
                       3. 使用Markdown格式
                       4. 包含章节标题`,
        },
    }
}

部署步骤

1. 安装Ollama

bash 复制代码
# Windows/Mac/Linux
curl -fsSL https://ollama.ai/install.sh | sh

# 或下载安装包:https://ollama.ai/download

2. 下载模型

bash 复制代码
# 推荐模型(根据显存选择)
ollama pull qwen2.5:7b      # 7B参数,需要约8GB显存
ollama pull qwen2.5:14b     # 14B参数,需要约16GB显存
ollama pull llama3.1:8b     # 8B参数,需要约10GB显存

# 查看已下载模型
ollama list

3. 启动服务

bash 复制代码
# Ollama默认会自动启动,也可以手动启动
ollama serve

# 测试API
curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5:7b",
  "messages": [{"role": "user", "content": "你好"}]
}'

4. 启动Go服务

bash 复制代码
# 设置环境变量
export AI_LLM_PROVIDER=ollama
export AI_LLM_BASE_URL=http://localhost:11434
export AI_MODEL=qwen2.5:7b

# 启动服务
go run cmd/server/main.go

性能优化建议

1. 模型选择

  • 7B模型:适合一般性任务,生成速度快
  • 14B模型:适合复杂推理,但需要更多资源
  • 量化版本:使用GGUF量化格式,减少内存占用

2. 参数调优

bash 复制代码
# 高质量但慢
OLLAMA_NUM_CTX=8192
OLLAMA_NUM_PREDICT=4096

# 快速但质量一般
OLLAMA_NUM_CTX=2048
OLLAMA_NUM_PREDICT=512

3. 硬件配置

  • 最低配置:8GB RAM + 4核CPU
  • 推荐配置:16GB RAM + 8核CPU + 8GB显存GPU
  • 高性能配置:32GB RAM + 16核CPU + 24GB显存GPU

4. 并发控制

go 复制代码
// 使用信号量限制并发数
var sem = make(chan struct{}, 3)  // 最多3个并发请求

func (s *AIService) GenerateNote(ctx context.Context, mediaID uint) error {
    sem <- struct{}{}        // 获取令牌
    defer func() { <-sem }() // 释放令牌

    // ... 生成逻辑
}

常见问题与解决方案

1. Ollama Runner崩溃

现象model runner has unexpectedly stopped

解决方案

bash 复制代码
# 减小上下文窗口
export OLLAMA_NUM_CTX=2048

# 禁用GPU(如果有CUDA错误)
export OLLAMA_NUM_GPU=0

# 增加系统交换空间

2. 生成速度慢

优化方案

  • 使用更小的模型(7B → 3B)
  • 启用GPU加速
  • 减小num_ctxnum_predict参数

3. 内存不足

解决方案

  • 使用量化模型:ollama pull qwen2.5:7b-q4_0
  • 增加系统内存或交换空间
  • 减少并发请求数

4. API调用失败

检查项

bash 复制代码
# 确认Ollama服务运行
curl http://localhost:11434/api/tags

# 查看日志
journalctl -u ollama  # Linux
# 或查看Ollama日志文件

总结

通过Ollama在本地部署大模型,我实现了:

  1. 成本可控:一次性硬件投入,长期零API费用
  2. 数据安全:敏感教学内容不出内网
  3. 灵活扩展:可根据需求选择不同规模模型
  4. 稳定可靠:不依赖外部API,避免限流和故障
相关推荐
爱睡懒觉的焦糖玛奇朵1 小时前
【从视频到数据集:焦糖玛奇朵的魔法工具Dataset Cleaner】
人工智能·python·学习·算法·yolo·音视频
邵宇然1 小时前
分布式存储系统设计:从一致性哈希到副本管理的 Rust 工程实现
人工智能
向量引擎1 小时前
我用AI给自己搭了一套热点证据系统
人工智能·gpt·aigc·文心一言·ai编程·ai写作·agi
邵宇然1 小时前
高性能 RPC 框架设计:从连接管理到零拷贝序列化的 Rust 工程实现
人工智能
梦想三三1 小时前
基于 PyTorch 的食物图像分类CNN 训练全流程
人工智能·pytorch·计算机视觉·cnn
xhtdj1 小时前
Build 2026:Azure API Management 推出统一模型 API 并新增 MCP 内容安全能力
人工智能·安全·azure
星恒随风1 小时前
C++ 内存管理详解:从内存分区、malloc/free 到 new/delete
开发语言·c++·笔记·学习
聆思科技AI芯片1 小时前
详解小聆AI语音视觉开发板实现语音点播本地TF卡中音乐的开发实现方法
人工智能
云器科技1 小时前
螳螂科技:从组装到统一,如何用云器 Lakehouse 完美替代“MC+DW+ADB”三件套?
数据库·数据仓库·人工智能