前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >大模型安装部署、测试、接入SpringCloud应用体系

大模型安装部署、测试、接入SpringCloud应用体系

原创
作者头像
后台技术汇
发布2024-09-22 10:02:03
670
发布2024-09-22 10:02:03
举报
文章被收录于专栏:后台技术汇

背景

大模型通常指的是具有庞大数据的神经网络模型,如OpenAI的GPT系列、Google的BERT等。这些模型对计算资源的需求极高,因此通常部署在云服务器或高性能计算集群上。安装部署大模型时,需要考虑模型的兼容性、计算资源的需求、存储空间的分配以及模型的优化策略。

SpringCloud是一个用于构建微服务架构的框架,它提供了一系列的开发工具和服务,如服务发现、配置管理、负载均衡等。

将大模型接入SpringCloud应用体系,可以实现模型的分布式部署、弹性扩展和高效管理。这一过程需要考虑模型的接口设计、数据传输的效率、安全性以及容错机制等。

交互式访问UI

仓库地址:https://github.com/ollama-ui/ollama-ui

这个项目名为Ollama UI,是一个简单的HTML UI,专为Ollama设计。

使用说明

  1. 克隆仓库:git clone https://github.com/ollama-ui/ollama-ui
  2. 进入克隆下来的目录:cd ollama-ui
  3. 启动项目:make open
  4. 在浏览器中打开:http://localhost:8000

应用集成大模型

最后我们需要针对业务,对大模型进行应用层面的定制化,比如接入到微服务体系,并赋能业务微服务。下面我挑选了几个常用的,Llama3.1的openApi来简要说明。

api介绍(其中4个)

代码语言:javascript
复制
POST /api/generate
POST /api/chat
POST /api/show
POST /api/embeddings

解析:

  1. /api/generate:生成给定提示的响应,该响应将使用所提供的模型。
  2. /api/chat:使用所提供的模型生成聊天中的下一条消息。
  3. /api/show:显示有关模型的信息,包括详细信息、Modelfile、模板、参数、许可证和系统提示。
  4. /api/embeddings:从模型生成嵌入

注意:详细的参数说明,可以参考接口文档 :https://ollama.fan/reference/api/#push-a-model-response

应用集成

创建maven工程

引入依赖

代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>olllama-integration</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../parent/pom.xml</relativePath>
    </parent>

    <properties>
        <!-- You can use later version here if available. -->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 注册中心客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- 客户端负载均衡 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/net.minidev/json-smart -->
        <dependency>
            <groupId>net.minidev</groupId>
            <artifactId>json-smart</artifactId>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-ollama -->
<!--        <dependency>-->
<!--            <groupId>org.springframework.ai</groupId>-->
<!--            <artifactId>spring-ai-ollama</artifactId>-->
<!--            <version>1.0.0-M1</version>-->
<!--        </dependency>-->

    </dependencies>
    <!-- This defines version of all Spring AI related dependencies -->
    <dependencyManagement>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
            <dependency>
                <groupId>com.googlecode.json-simple</groupId>
                <artifactId>json-simple</artifactId>
                <version>1.1.1</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/net.minidev/json-smart -->
            <dependency>
                <groupId>net.minidev</groupId>
                <artifactId>json-smart</artifactId>
                <version>2.5.1</version>
            </dependency>

            <!--            <dependency>-->
<!--                <groupId>org.springframework.ai</groupId>-->
<!--                <artifactId>spring-ai-bom</artifactId>-->
<!--                <version>1.0.0-M1</version>-->
<!--                <type>pom</type>-->
<!--                <scope>import</scope>-->
<!--            </dependency>-->
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <!-- As Spring AI 1.0.0 is not yet released and available in Maven central, we'll need a different repository. -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <releases>
                <enabled>false</enabled>
            </releases>
        </repository>
    </repositories>
</project>

项目配置文件

application.properties

代码语言:javascript
复制
spring.application.name=ollama-integration

## 配置ollama模型参数
ollama.enable=true
ollama.base-url: localhost:11434
ollama.model-name: ollama

bootstrap.properties

代码语言:txt
复制

server.port=11444

## 注册中心配置

###################################  注册中心  ######################################################
## eurekaClient:服务注册中心的地址
#eureka.client.serviceUrl.defaultZone=http://localhost:8881/eureka/

## eurekaClient:服务注册中心集群的地址
eureka.client.serviceUrl.defaultZone=http://localhost:8881/eureka/,http://localhost2:8882/eureka/
# 拉取缓存清单开关
eureka.client.fetch-registry=true
# 修改缓存清单的更新时间
eureka.client.registry-fetch-interval-seconds=20

启动类

代码语言:txt
复制
package com.bryant;

import java.time.Duration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * 通过SpringAI框架,集成ollama大模型,并请求
 * 参考:
 *  - https://blog.csdn.net/weixin_54925172/article/details/138815936
 *  -
 */
@SpringBootApplication
@EnableDiscoveryClient
public class OllamaIntegrationServer {

    public static void main(String[] args) {
        SpringApplication.run(OllamaIntegrationServer.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate;
    }

    /**
     * 带超时时间的RestTemplate
     * @param restTemplateBuilder
     * @return
     */
    @Bean("timeOutRestTemplate")
    public RestTemplate restTemplate2(RestTemplateBuilder restTemplateBuilder) {
        return restTemplateBuilder
                .setConnectTimeout(Duration.ofSeconds(60))
                .setReadTimeout(Duration.ofSeconds(60))
                .build();
    }
}

配置类

代码语言:txt
复制
package com.bryant.config;

import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnProperty(prefix = "ollama", name = "enable", havingValue = "true", matchIfMissing = false)
@Data
public class OllamaConfig {

    private String modelName;
    private String baseUrl;

}

public class OllamaConstants {

    public static final String AI_ASK_PROMPT_TEMPLATE = "I am a student from the University of Washington."
            + "I want to ask you a question: %s ";
    public static String CITY_GUIDE_PROMPT_TEMPLATE = "I am a tourist visiting the city of %s."
            + "I am mostly interested in %s."
            + "Tell me tips on what to do there.";

    public static final String OLLAMA_MODEL_NAME = "llama3";

    public static final String OLLAMA_URL = "http://127.0.0.1:11434";
    //生成补全 POST
    public static final String API_GENERATE = OLLAMA_URL + "/api/generate";
    //对话补全 POST
    public static final String API_CHAT = OLLAMA_URL + "/api/chat";
    //列出本地模型
    public static final String API_LIST = OLLAMA_URL + "/api/tags";
    //显示模型信息
    public static final String API_SHOW = OLLAMA_URL + "/api/show";
    //生成嵌入
    public static final String API_EMBEDDINGS = OLLAMA_URL + "/api/embeddings";

}

接口服务

Controller

代码语言:txt
复制
package com.bryant.controller;

import com.bryant.service.ChatService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AiController {

    private final ChatService chatService;

    public AiController(ChatService chatService) {
        this.chatService = chatService;
    }

    @GetMapping("/city-guide")
    public String askAi(
            @RequestParam("city") String city,
            @RequestParam("interest") String interest) {
        return chatService.getCityGuide(city, interest);
    }

    @GetMapping("/ask_ai")
    public String cityGuide(@RequestParam("question") String question) {
        return chatService.askAi(question);
    }

    @PostMapping("/embedding")
    public String embedding(
            @RequestParam("prompt") String prompt,
            @RequestParam("temperature") Integer temperature) {
        return chatService.embedding(prompt, temperature);
    }

    @GetMapping("/model_show")
    public String modelShow() {
        return chatService.modelShow();
    }

}

Service

代码语言:txt
复制
package com.bryant.service;

import com.bryant.config.OllamaConstants;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ChatService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    @Qualifier("timeOutRestTemplate")
    private RestTemplate timeOutRestTemplate;

    public String getCityGuide(String city, String interest) {
        String prompt = String.format(OllamaConstants.CITY_GUIDE_PROMPT_TEMPLATE, city, interest);
        HashMap<String, Object> map = new HashMap<>();
        map.put("prompt", prompt);
        map.put("model", OllamaConstants.OLLAMA_MODEL_NAME);
        map.put("stream", false);
        ResponseEntity<JsonNode> stringResponseEntity = timeOutRestTemplate.postForEntity(OllamaConstants.API_GENERATE, map, JsonNode.class);
        HttpStatus statusCode = stringResponseEntity.getStatusCode();

        // 大模型请求成功
        if (statusCode != HttpStatus.OK) {
            return "first request to ollama failed";
        }

        JsonNode body = stringResponseEntity.getBody();
        JsonNode firstAnswerResponseText = body.get("response");

        // 第二轮对话
        map.put("prompt", "so can you tell me more about it?");
        map.put("model", OllamaConstants.OLLAMA_MODEL_NAME);
        map.put("context", body.get("context"));
        map.put("stream", false);
        ResponseEntity<JsonNode> stringResponseEntity2 = timeOutRestTemplate.postForEntity(OllamaConstants.API_GENERATE, map, JsonNode.class);
        JsonNode body2 = stringResponseEntity2.getBody();
        JsonNode firstAnswerResponseText2 =  body2.get("response");

        return "firstAnswerResponseText: " + firstAnswerResponseText.asText()
                + "\n"
                + " secondAnswerResponseText: " + firstAnswerResponseText2.asText();
    }

    public String askAi(String question) {
        String prompt = String.format(OllamaConstants.AI_ASK_PROMPT_TEMPLATE, question);
        HashMap<String, Object> map = new HashMap<>();
        map.put("prompt", prompt);
        map.put("model", OllamaConstants.OLLAMA_MODEL_NAME);
        map.put("stream", false);
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(OllamaConstants.API_GENERATE, map, String.class);
        return stringResponseEntity.getBody();
    }

    public String embedding(String prompt, Integer temperature) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("prompt", prompt);
        map.put("model", OllamaConstants.OLLAMA_MODEL_NAME);
        HashMap<String, Object> options = new HashMap<>();
        map.put("options", options);
        // temperature  模型的温度。增加温度将使模型回答更具创造性。(默认:0.8)
        options.put("temperature", temperature);
        map.put("stream", false);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(OllamaConstants.API_EMBEDDINGS, map, String.class);
        return responseEntity.getBody();
    }

    public String modelShow() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("model", OllamaConstants.OLLAMA_MODEL_NAME);
        map.put("stream", false);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(OllamaConstants.API_SHOW, map, String.class);
        return responseEntity.getBody();
    }
}

注册中心启动

大模型应用已经集成到SpringCloud微服务

图片
图片

接口测试结果

api访问大模型,并取到大模型结果。

http://localhost:11444/city-guide?city=beijing&interest=fishing

图片
图片

http://localhost:11444/city-guide?city=beijing&interest=fishing

图片
图片

http://localhost:11444/model_show

图片
图片

embedding

http://localhost:11444/embedding?prompt=sky is red&temperature=0

图片
图片

结果分析

每个请求大模型,都会返回详细的执行步骤耗时,如下:

代码语言:txt
复制

"total_duration":16875943917,
"load_duration":3372417,
"prompt_eval_count":31,
"prompt_eval_duration":292574000,
"eval_count":502,
"eval_duration":16578831000
  • total_duration:生成响应的时间
  • load_duration:加载模型的时间(纳秒)
  • prompt_eval_count:提示中的令牌token数量
  • prompt_eval_duration:评估提示的时间(纳秒)
  • eval_count:响应中的令牌token数量
  • eval_duration:生成响应所花费的时间(纳秒)
  • context:此响应中使用的会话的编码,这可以在下一个请求中发送以保持会话记忆
  • response:如果响应是流式的,则为空;如果不是流式的,则会包含完整响应

拓展

生成embedding

大型语言模型可以生成上下文相关的embedding表示,这些embedding可以更好地捕捉单词的语义和上下文信息。

embedding向量是包含语义信息的。也就是含义相近的单词,embedding向量在空间中有相似的位置,但是,除此之外,embedding也有其它优点。

Embedding重要性

而embedding重要的原因在于它可以表示单词或者语句的语义。实值向量的embedding可以表示单词的语义,主要是因为这些embedding向量是根据单词在语言上下文中的出现模式进行学习的。

例如,如果一个单词在一些上下文中经常与另一个单词一起出现,那么这两个单词的嵌入向量在向量空间中就会有相似的位置。这意味着它们有相似的含义和语义。

Embedding在大模型中的价值

前面说的其实都是Embedding在之前的价值。但是,大语言模型时代,例如ChatGPT这样的模型流行之后,大家发现embedding有了新的价值,即解决大模型的输入限制。

此前,OpenAI官方也发布了一个案例,即如何使用embedding来解决长文本输入问题,我们DataLearner官方博客也介绍了这个教程:OpenAI官方教程:如何使用基于embeddings检索来解决GPT无法处理长文本和最新数据的问题。

像 GPT-3 这样的语言模型有一个限制,即它们可以处理的输入文本量有限。这个限制通常在几千到数万个tokens之间,具体取决于模型架构和可用的硬件资源。

其他文章

微服务重构:Mysql+DTS+Kafka+ElasticSearch解决跨表检索难题

基于SpringMVC的API灰度方案

SQL治理经验谈:索引覆盖

Mybatis链路分析:JDK动态代理和责任链模式的应用 大模型安装部署、测试、接入SpringCloud应用体系

一文带你看懂:亿级大表垂直拆分的工程实践

亿级大表冷热分级的工程实践

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 交互式访问UI
    • 使用说明
    • 应用集成大模型
      • api介绍(其中4个)
        • 应用集成
          • 创建maven工程
          • 引入依赖
        • 项目配置文件
          • 启动类
            • 配置类
              • 接口服务
                • Controller
              • Service
                • 注册中心启动
                  • 接口测试结果
                    • 结果分析
                • 拓展
                  • 生成embedding
                    • Embedding重要性
                      • Embedding在大模型中的价值
                      • 其他文章
                      相关产品与服务
                      微服务引擎 TSE
                      微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档