ETJava Beta | Java    注册   登录
  • 搜索:
  • ollama搭建本地ai大模型并应用调用

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/ggtop/p/18368333
    如有侵权 请联系我们删除  (页面底部联系我们)  

    1、下载ollama

    1)https://ollama.com 进入网址,点击download下载
    2)下载后直接安装即可。

    2、启动配置模型

    默认是启动cmd窗口直接输入

    1 ollama run llama3
     
      

    启动llama3大模型 或者启动千问大模型

    1 ollama run qwen2
     
      

    启动输入你需要输入的问题即可

     

    3、配置UI界面

    安装docker
    并部署web操作界面

    1 docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui --restart always ghcr.io/open-webui/open-webui:main

    安装完毕后,安装包较大,需等待一段时间。
    localhost:3000即可打开网址

     

    4、搭建本地知识库

    AnythingLLM

    5、配置文件

    开发11434端口,便于外部访问接口,如果跨域访问的话配置OLLAMA_ORIGINS=*

    Windows版

    只需要在系统环境变量中直接配置,

    OLLAMA_HOST为变量名,"0.0.0.0:11434"为变量值

    1 OLLAMA_HOST= "0.0.0.0:11434"

    MAC版

    配置OLLAMA_HOST

    1 sudo sh -c 'echo "export OLLAMA_HOST=0.0.0.0:11434">>/etc/profile'launchctl setenv OLLAMA_HOST "0.0.0.0:11434"

    Linux版

    配置OLLAMA_HOST

    1 Environment="OLLAMA\_HOST=0.0.0.0"

    6、程序调用接口

    golang实现例子:流式响应速度更快,用户体验更佳。

    golang例子:非流式响应

    package main

    import (
    "bufio"
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "strings"
    "time"
    )

    const (
    obaseURL = "http://localhost:11434/api"
    omodelID = "qwen2:0.5b" // 选择合适的模型
    oendpoint = "/chat" //"/chat/completions"
    )

    // ChatCompletionRequest 定义了请求体的结构
    type olChatCompletionRequest struct {
    Model string `json:"model"`
    Messages []struct {
    Role string `json:"role"`
    Content string `json:"content"`
    } `json:"messages"`
    Stream bool `json:"stream"`
    //Temperature float32 `json:"temperature"`
    }

    // ChatCompletionResponse 定义了响应体的结构
    type olChatCompletionResponse struct {
    //Choices []struct {
    Message struct {
    Role string `json:"role"`
    Content string `json:"content"`
    } `json:"message"`
    //} `json:"choices"`
    }

    // sendRequestWithRetry 发送请求并处理可能的429错误
    func olsendRequestWithRetry(client *http.Client, requestBody []byte) (*http.Response, error) {
    req, err := http.NewRequest("POST", obaseURL+oendpoint, bytes.NewBuffer(requestBody))
    if err != nil {
    return nil, err
    }

    req.Header.Set("Content-Type", "application/json")
    //req.Header.Set("Authorization", "Bearer "+apiKey)

    resp, err := client.Do(req)
    if err != nil {
    return nil, err
    }

    if resp.StatusCode == http.StatusTooManyRequests {
    retryAfter := resp.Header.Get("Retry-After")
    if retryAfter != "" {
    duration, _ := time.ParseDuration(retryAfter)
    time.Sleep(duration)
    } else {
    time.Sleep(5 * time.Second) // 默认等待5秒
    }
    return olsendRequestWithRetry(client, requestBody) // 递归重试
    }

    return resp, nil
    }

    func main() {
    client := &http.Client{} // 创建一个全局的 HTTP 客户端实例

    // 初始化对话历史记录
    history := []struct {
    Role string `json:"role"`
    Content string `json:"content"`
    }{
    {"system", "你是一位唐代诗人,特别擅长模仿李白的风格。"},
    }

    // 创建标准输入的扫描器
    scanner := bufio.NewScanner(os.Stdin)

    for {
    fmt.Print("请输入您的问题(或者输入 'exit' 退出): ")
    scanner.Scan()
    userInput := strings.TrimSpace(scanner.Text())

    // 退出条件
    if userInput == "exit" {
    fmt.Println("感谢使用,再见!")
    break
    }

    // 添加用户输入到历史记录
    history = append(history, struct {
    Role string `json:"role"`
    Content string `json:"content"`
    }{
    "user",
    userInput,
    })

    // 创建请求体
    requestBody := olChatCompletionRequest{
    Model: omodelID,
    Messages: history,
    Stream: false,
    //Temperature: 0.7,
    }

    // 构建完整的请求体,包含历史消息
    requestBody.Messages = append([]struct {
    Role string `json:"role"`
    Content string `json:"content"`
    }{
    {
    Role: "system",
    Content: "你是一位唐代诗人,特别擅长模仿李白的风格。",
    },
    }, history...)

    // 将请求体序列化为 JSON
    requestBodyJSON, err := json.Marshal(requestBody)
    if err != nil {
    fmt.Println("Error marshalling request body:", err)
    continue
    }
    fmt.Println("wocao:" + string(requestBodyJSON))
    // 发送请求并处理重试
    resp, err := olsendRequestWithRetry(client, requestBodyJSON)
    if err != nil {
    fmt.Println("Error sending request after retries:", err)
    continue
    }
    defer resp.Body.Close()

    // 检查响应状态码
    if resp.StatusCode != http.StatusOK {
    fmt.Printf("Received non-200 response status code: %d\n", resp.StatusCode)
    continue
    }

    // 读取响应体
    responseBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
    fmt.Println("Error reading response body:", err)
    continue
    }
    //fmt.Println("0000" + string(responseBody))
    // 解析响应体
    var completionResponse olChatCompletionResponse
    err = json.Unmarshal(responseBody, &completionResponse)
    if err != nil {
    fmt.Println("Error unmarshalling response body:", err)
    continue
    }
    fmt.Printf("AI 回复: %s\n", completionResponse.Message.Content) // choice.Message.Content
    // 将用户的消息添加到历史记录中
    history = append(history, struct {
    Role string `json:"role"`
    Content string `json:"content"`
    }{
    Role: completionResponse.Message.Role,
    Content: completionResponse.Message.Content, // 假设用户的消息是第一个
    }) 

    }
    }

     

    golang例子:流式响应
      1 package main
      2 
      3 import (
      4     "bufio"
      5     "bytes"
      6     "encoding/json"
      7     "fmt"
      8     "io"
      9     "net/http"
     10     "os"
     11     "strings"
     12     "time"
     13 )
     14 
     15 const (
     16     obaseURL  = "http://localhost:11434/api" 
     17     omodelID  = "qwen2:0.5b"                 // 选择合适的模型
     18     oendpoint = "/chat"                      //"/chat/completions"
     19 )
     20 
     21 // ChatCompletionRequest 定义了请求体的结构
     22 type olChatCompletionRequest struct {
     23     Model    string `json:"model"`
     24     Messages []struct {
     25         Role    string `json:"role"`
     26         Content string `json:"content"`
     27     } `json:"messages"`
     28     Stream bool `json:"stream"`
     29     //Temperature float32 `json:"temperature"`
     30 }
     31 
     32 // ChatCompletionResponse 定义了响应体的结构
     33 type olChatCompletionResponse struct {
     34     //Choices []struct {
     35     Message struct {
     36         Role    string `json:"role"`
     37         Content string `json:"content"`
     38     } `json:"message"`
     39     //} `json:"choices"`
     40 }
     41 
     42 // sendRequestWithRetry 发送请求并处理可能的429错误
     43 func olsendRequestWithRetry(client *http.Client, requestBody []byte) (*http.Response, error) {
     44     req, err := http.NewRequest("POST", obaseURL+oendpoint, bytes.NewBuffer(requestBody))
     45     if err != nil {
     46         return nil, err
     47     }
     48 
     49     req.Header.Set("Content-Type", "application/json")
     50     //req.Header.Set("Authorization", "Bearer "+apiKey)
     51 
     52     resp, err := client.Do(req)
     53     if err != nil {
     54         return nil, err
     55     }
     56 
     57     if resp.StatusCode == http.StatusTooManyRequests {
     58         retryAfter := resp.Header.Get("Retry-After")
     59         if retryAfter != "" {
     60             duration, _ := time.ParseDuration(retryAfter)
     61             time.Sleep(duration)
     62         } else {
     63             time.Sleep(5 * time.Second) // 默认等待5秒
     64         }
     65         return olsendRequestWithRetry(client, requestBody) // 递归重试
     66     }
     67 
     68     return resp, nil
     69 }
     70 
     71 func main() {
     72     client := &http.Client{} // 创建一个全局的 HTTP 客户端实例
     73 
     74     // 初始化对话历史记录
     75     history := []struct {
     76         Role    string `json:"role"`
     77         Content string `json:"content"`
     78     }{
     79         {"system", "你是一位唐代诗人,特别擅长模仿李白的风格。"},
     80     }
     81 
     82     // 创建标准输入的扫描器
     83     scanner := bufio.NewScanner(os.Stdin)
     84 
     85     for {
     86         fmt.Print("请输入您的问题(或者输入 'exit' 退出): ")
     87         scanner.Scan()
     88         userInput := strings.TrimSpace(scanner.Text())
     89 
     90         // 退出条件
     91         if userInput == "exit" {
     92             fmt.Println("感谢使用,再见!")
     93             break
     94         }
     95 
     96         // 添加用户输入到历史记录
     97         history = append(history, struct {
     98             Role    string `json:"role"`
     99             Content string `json:"content"`
    100         }{
    101             "user",
    102             userInput,
    103         })
    104 
    105         // 创建请求体
    106         requestBody := olChatCompletionRequest{
    107             Model:    omodelID,
    108             Messages: history,
    109             Stream:   true,
    110             //Temperature: 0.7,
    111         }
    112 
    113         // 构建完整的请求体,包含历史消息
    114         requestBody.Messages = append([]struct {
    115             Role    string `json:"role"`
    116             Content string `json:"content"`
    117         }{
    118             {
    119                 Role:    "system",
    120                 Content: "你是一位唐代诗人,特别擅长模仿李白的风格。",
    121             },
    122         }, history...)
    123 
    124         // 将请求体序列化为 JSON
    125         requestBodyJSON, err := json.Marshal(requestBody)
    126         if err != nil {
    127             fmt.Println("Error marshalling request body:", err)
    128             continue
    129         }
    130         fmt.Println("wocao:" + string(requestBodyJSON))
    131         // 发送请求并处理重试
    132         resp, err := olsendRequestWithRetry(client, requestBodyJSON)
    133         if err != nil {
    134             fmt.Println("Error sending request after retries:", err)
    135             continue
    136         }
    137         defer resp.Body.Close()
    138 
    139         // 检查响应状态码
    140         if resp.StatusCode != http.StatusOK {
    141             fmt.Printf("Received non-200 response status code: %d\n", resp.StatusCode)
    142             continue
    143         }
    144                resutlmessage := ""
    145         streamReader := resp.Body
    146         buf := make([]byte, 1024) // 或者使用更大的缓冲区来提高读取性能
    147         var completionResponse olChatCompletionResponse
    148         fmt.Print("AI 回复:")
    149         for {
    150             n, err := streamReader.Read(buf)
    151             if n > 0 {
    152                 // 处理接收到的数据,这里简单打印出来
    153                 //fmt.Print(string(buf[:n]))
    154                 err = json.Unmarshal(buf[:n], &completionResponse)
    155                 fmt.Print(string(completionResponse.Message.Content))
    156                                resutlmessage+=string(completionResponse.Message.Content)
    157                 if err != nil {
    158                     fmt.Println("Error unmarshalling response body:", err)
    159                     continue
    160                 }
    161             }
    162             if err != nil {
    163                 if err == io.EOF {
    164                     fmt.Println("")
    165                     break
    166                 }
    167                 panic(err)
    168             }
    169         }
    170 
    171         // 将用户的消息添加到历史记录中
    172         history = append(history, struct {
    173             Role    string `json:"role"`
    174             Content string `json:"content"`
    175         }{
    176             Role:    completionResponse.Message.Role,
    177             Content: resutlmessage,//completionResponse.Message.Content, // 假设用户的消息是第一个
    178         })
    179     }
    180 }

     


    感谢观看,谢谢!