Преглед изворни кода

增加llm相关数据的后台管理功能

luoshi пре 1 година
родитељ
комит
c3eb2c1966
21 измењених фајлова са 502 додато и 26 уклоњено
  1. 19 0
      src/main/java/com/qmth/ops/api/controller/admin/LlmInfoController.java
  2. 63 0
      src/main/java/com/qmth/ops/api/controller/admin/LlmModelController.java
  3. 71 0
      src/main/java/com/qmth/ops/api/controller/admin/LlmOrgConfigController.java
  4. 50 0
      src/main/java/com/qmth/ops/api/controller/admin/LlmSupplierController.java
  5. 7 6
      src/main/java/com/qmth/ops/api/controller/ai/LlmController.java
  6. 10 1
      src/main/java/com/qmth/ops/api/security/Permission.java
  7. 78 0
      src/main/java/com/qmth/ops/api/vo/LlmOrgConfigVO.java
  8. 53 0
      src/main/java/com/qmth/ops/api/vo/LlmSupplierVO.java
  9. 3 3
      src/main/java/com/qmth/ops/biz/ai/client/ChatApiClient.java
  10. 11 0
      src/main/java/com/qmth/ops/biz/ai/client/ChatApiConfig.java
  11. 3 0
      src/main/java/com/qmth/ops/biz/dao/LlmOrgConfigDao.java
  12. 7 0
      src/main/java/com/qmth/ops/biz/dao/LlmPromptTemplateDao.java
  13. 2 2
      src/main/java/com/qmth/ops/biz/domain/LlmPromptTemplate.java
  14. 51 0
      src/main/java/com/qmth/ops/biz/query/LlmOrgConfigQuery.java
  15. 13 1
      src/main/java/com/qmth/ops/biz/service/LlmClientService.java
  16. 10 6
      src/main/java/com/qmth/ops/biz/service/LlmOrgConfigService.java
  17. 22 3
      src/main/java/com/qmth/ops/biz/service/LlmPromptTemplateService.java
  18. 2 1
      src/main/java/com/qmth/ops/biz/service/OrgService.java
  19. 0 1
      src/main/resources/application.properties
  20. 25 0
      src/main/resources/mapper/LlmOrgConfigMapper.xml
  21. 2 2
      src/main/resources/script/init.sql

+ 19 - 0
src/main/java/com/qmth/ops/api/controller/admin/LlmInfoController.java

@@ -0,0 +1,19 @@
+package com.qmth.ops.api.controller.admin;
+
+import com.qmth.boot.api.annotation.Aac;
+import com.qmth.boot.core.ai.model.llm.LlmAppType;
+import com.qmth.ops.api.constants.OpsApiConstants;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(OpsApiConstants.ADMIN_URI_PREFIX + "/llm")
+public class LlmInfoController {
+
+    @RequestMapping("/app_types")
+    @Aac(auth = false)
+    public Object list() {
+        return LlmAppType.values();
+    }
+
+}

+ 63 - 0
src/main/java/com/qmth/ops/api/controller/admin/LlmModelController.java

@@ -0,0 +1,63 @@
+package com.qmth.ops.api.controller.admin;
+
+import com.qmth.ops.api.constants.OpsApiConstants;
+import com.qmth.ops.api.security.AdminSession;
+import com.qmth.ops.api.security.Permission;
+import com.qmth.ops.biz.domain.LlmModel;
+import com.qmth.ops.biz.domain.LlmPromptTemplate;
+import com.qmth.ops.biz.service.LlmClientService;
+import com.qmth.ops.biz.service.LlmModelService;
+import com.qmth.ops.biz.service.LlmPromptTemplateService;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@RestController
+@RequestMapping(OpsApiConstants.ADMIN_URI_PREFIX + "/llm/model")
+public class LlmModelController {
+
+    @Resource
+    private LlmModelService llmModelService;
+
+    @Resource
+    private LlmPromptTemplateService llmPromptTemplateService;
+
+    @Resource
+    private LlmClientService llmClientService;
+
+    @PostMapping("/list")
+    public List<LlmModel> list(@RequestParam Long supplierId) {
+        return llmModelService.listBySupplier(supplierId);
+    }
+
+    @PostMapping("/insert")
+    public LlmModel insert(@RequestAttribute AdminSession adminSession, LlmModel model) {
+        adminSession.hasPermission(Permission.LLM_MODEL_INSERT);
+        model = llmModelService.insert(model);
+        llmClientService.updateByModel(model);
+        return model;
+    }
+
+    @PostMapping("/update")
+    public LlmModel update(@RequestAttribute AdminSession adminSession, LlmModel model) {
+        adminSession.hasPermission(Permission.LLM_MODEL_EDIT);
+        llmModelService.update(model);
+        llmClientService.updateByModel(model);
+        return llmModelService.getById(model.getId());
+    }
+
+    @PostMapping("/prompt_template/list")
+    public List<LlmPromptTemplate> getPromptTemplate(@RequestParam Long modelId) {
+        return llmPromptTemplateService.findByModel(modelId);
+    }
+
+    @PostMapping("/prompt_template/update")
+    public LlmPromptTemplate updatePromptTemplate(@RequestAttribute AdminSession adminSession,
+            LlmPromptTemplate template) {
+        adminSession.hasPermission(Permission.LLM_MODEL_EDIT);
+        llmPromptTemplateService.update(template);
+        return llmPromptTemplateService.findByModelAndAppType(template.getModelId(), template.getAppType());
+    }
+
+}

+ 71 - 0
src/main/java/com/qmth/ops/api/controller/admin/LlmOrgConfigController.java

@@ -0,0 +1,71 @@
+package com.qmth.ops.api.controller.admin;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.ops.api.constants.OpsApiConstants;
+import com.qmth.ops.api.security.AdminSession;
+import com.qmth.ops.api.security.Permission;
+import com.qmth.ops.api.vo.LlmOrgConfigVO;
+import com.qmth.ops.api.vo.OrgVO;
+import com.qmth.ops.biz.domain.LlmModel;
+import com.qmth.ops.biz.domain.LlmOrgConfig;
+import com.qmth.ops.biz.domain.Org;
+import com.qmth.ops.biz.query.LlmOrgConfigQuery;
+import com.qmth.ops.biz.service.LlmModelService;
+import com.qmth.ops.biz.service.LlmOrgConfigService;
+import com.qmth.ops.biz.service.LlmSupplierService;
+import com.qmth.ops.biz.service.OrgService;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping(OpsApiConstants.ADMIN_URI_PREFIX + "/llm/org_config")
+public class LlmOrgConfigController {
+
+    @Resource
+    private OrgService orgService;
+
+    @Resource
+    private LlmSupplierService llmSupplierService;
+
+    @Resource
+    private LlmModelService llmModelService;
+
+    @Resource
+    private LlmOrgConfigService llmOrgConfigService;
+
+    @PostMapping("/query")
+    public IPage<LlmOrgConfigVO> query(LlmOrgConfigQuery query) {
+        return llmOrgConfigService.query(query).convert(config -> {
+            LlmModel model = llmModelService.getById(config.getModelId());
+            Org org = orgService.getById(config.getOrgId());
+            return new LlmOrgConfigVO(llmSupplierService.getById(model.getSupplierId()), model, new OrgVO(org), config);
+        });
+    }
+
+    @PostMapping("/insert")
+    public LlmOrgConfig insert(@RequestAttribute AdminSession adminSession, LlmOrgConfig config) {
+        adminSession.hasPermission(Permission.LLM_ORG_CONFIG_INSERT);
+        config.setLeftCount(config.getPermitCount());
+        llmOrgConfigService.save(config);
+        return config;
+    }
+
+    @PostMapping("/update/model")
+    public LlmOrgConfig updateModel(@RequestAttribute AdminSession adminSession, LlmOrgConfig config) {
+        adminSession.hasPermission(Permission.LLM_ORG_CONFIG_EDIT);
+        llmOrgConfigService.updateModel(config);
+        return llmOrgConfigService.findByOrgAndAppType(config.getOrgId(), config.getAppType());
+    }
+
+    @PostMapping("/update/permit_count")
+    public LlmOrgConfig updatePermit(@RequestAttribute AdminSession adminSession, LlmOrgConfig config) {
+        adminSession.hasPermission(Permission.LLM_ORG_CONFIG_EDIT);
+        llmOrgConfigService.permit(config, config.getPermitCount());
+        return llmOrgConfigService.findByOrgAndAppType(config.getOrgId(), config.getAppType());
+    }
+
+}

+ 50 - 0
src/main/java/com/qmth/ops/api/controller/admin/LlmSupplierController.java

@@ -0,0 +1,50 @@
+package com.qmth.ops.api.controller.admin;
+
+import com.qmth.ops.api.constants.OpsApiConstants;
+import com.qmth.ops.api.security.AdminSession;
+import com.qmth.ops.api.security.Permission;
+import com.qmth.ops.api.vo.LlmSupplierVO;
+import com.qmth.ops.biz.domain.LlmSupplier;
+import com.qmth.ops.biz.service.LlmClientService;
+import com.qmth.ops.biz.service.LlmSupplierService;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping(OpsApiConstants.ADMIN_URI_PREFIX + "/llm/supplier")
+public class LlmSupplierController {
+
+    @Resource
+    private LlmSupplierService llmSupplierService;
+
+    @Resource
+    private LlmClientService llmClientService;
+
+    @PostMapping("/list")
+    public List<LlmSupplierVO> list() {
+        return llmSupplierService.list().stream().map(LlmSupplierVO::new).collect(Collectors.toList());
+    }
+
+    @PostMapping("/detail")
+    public LlmSupplier detail(@RequestParam Long id) {
+        return llmSupplierService.getById(id);
+    }
+
+    @PostMapping("/insert")
+    public LlmSupplier insert(@RequestAttribute AdminSession adminSession, LlmSupplier supplier) {
+        adminSession.hasPermission(Permission.LLM_SUPPLIER_INSERT);
+        return llmSupplierService.insert(supplier);
+    }
+
+    @PostMapping("/update")
+    public LlmSupplier update(@RequestAttribute AdminSession adminSession, LlmSupplier supplier) {
+        adminSession.hasPermission(Permission.LLM_SUPPLIER_EDIT);
+        llmSupplierService.update(supplier);
+        llmClientService.updateBySupplier(supplier);
+        return llmSupplierService.getById(supplier.getId());
+    }
+
+}

+ 7 - 6
src/main/java/com/qmth/ops/api/controller/ai/LlmController.java

@@ -36,7 +36,7 @@ public class LlmController {
     public ChatResult chat(@RequestAttribute AccessOrg accessOrg,
             @RequestHeader(AiConstants.LLM_APP_TYPE_HEADER) LlmAppType type,
             @RequestBody @Validated ChatRequest request) throws Exception {
-        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg(), type);
+        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg().getId(), type);
         if (config == null || config.getLeftCount() <= 0) {
             throw new ForbiddenException(
                     "Chat api is disabled or exhausted for org=" + accessOrg.getOrg().getCode() + ", app_type=" + type);
@@ -50,12 +50,12 @@ public class LlmController {
     public ChatResult chatTemplate(@RequestAttribute AccessOrg accessOrg,
             @RequestHeader(AiConstants.LLM_APP_TYPE_HEADER) LlmAppType type, @RequestBody Map<String, Object> param)
             throws Exception {
-        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg(), type);
+        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg().getId(), type);
         if (config == null || config.getLeftCount() <= 0) {
             throw new ForbiddenException(
                     "Chat api is disabled or exhausted for org=" + accessOrg.getOrg().getCode() + ", app_type=" + type);
         }
-        LlmPromptTemplate llmPromptTemplate = llmPromptTemplateService.findByAppType(type, config.getModelId());
+        LlmPromptTemplate llmPromptTemplate = llmPromptTemplateService.findByModelAndAppType(config.getModelId(), type);
         if (llmPromptTemplate == null) {
             throw new NotFoundException(
                     "Chat prompt template not found for app_type=" + type + ", modelId=" + config.getModelId());
@@ -76,7 +76,7 @@ public class LlmController {
     public LlmAppBalance balance(@RequestAttribute AccessOrg accessOrg,
             @RequestHeader(AiConstants.LLM_APP_TYPE_HEADER) LlmAppType type) {
         LlmAppBalance balance = new LlmAppBalance();
-        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg(), type);
+        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg().getId(), type);
         if (config != null) {
             balance.setPermitCount(config.getPermitCount());
             balance.setLeftCount(config.getLeftCount());
@@ -88,9 +88,10 @@ public class LlmController {
     public PromptTemplate getPromptTemplate(@RequestAttribute AccessOrg accessOrg,
             @RequestHeader(AiConstants.LLM_APP_TYPE_HEADER) LlmAppType type) {
         PromptTemplate template = new PromptTemplate();
-        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg(), type);
+        LlmOrgConfig config = llmOrgConfigService.findByOrgAndAppType(accessOrg.getOrg().getId(), type);
         if (config != null) {
-            LlmPromptTemplate llmPromptTemplate = llmPromptTemplateService.findByAppType(type, config.getModelId());
+            LlmPromptTemplate llmPromptTemplate = llmPromptTemplateService
+                    .findByModelAndAppType(config.getModelId(), type);
             if (llmPromptTemplate != null) {
                 template.setSystem(llmPromptTemplate.getSystem());
                 template.setUser(llmPromptTemplate.getUser());

+ 10 - 1
src/main/java/com/qmth/ops/api/security/Permission.java

@@ -36,7 +36,16 @@ public enum Permission {
     WXAPP_EDIT("微信小程序修改", null),
     USER_VIEW("用户管理", null),
     USER_INSERT("用户新增", null),
-    USER_EDIT("用户修改", null);
+    USER_EDIT("用户修改", null),
+    LLM_SUPPLIER_VIEW("大模型服务商管理", null),
+    LLM_SUPPLIER_INSERT("大模型服务商新增", null),
+    LLM_SUPPLIER_EDIT("大模型服务商修改", null),
+    LLM_MODEL_VIEW("大模型模型管理", null),
+    LLM_MODEL_INSERT("大模型模型新增", null),
+    LLM_MODEL_EDIT("大模型模型修改", null),
+    LLM_ORG_CONFIG_VIEW("大模型机构配额管理", null),
+    LLM_ORG_CONFIG_INSERT("大模型机构配额新增", null),
+    LLM_ORG_CONFIG_EDIT("大模型机构配额修改", null);
 
     private String name;
 

+ 78 - 0
src/main/java/com/qmth/ops/api/vo/LlmOrgConfigVO.java

@@ -0,0 +1,78 @@
+package com.qmth.ops.api.vo;
+
+import com.qmth.boot.core.ai.model.llm.LlmAppType;
+import com.qmth.ops.biz.domain.LlmModel;
+import com.qmth.ops.biz.domain.LlmOrgConfig;
+import com.qmth.ops.biz.domain.LlmSupplier;
+
+public class LlmOrgConfigVO {
+
+    private OrgVO org;
+
+    private LlmModel model;
+
+    private LlmSupplierVO supplier;
+
+    private LlmAppType appType;
+
+    private int permitCount;
+
+    private int leftCount;
+
+    public LlmOrgConfigVO(LlmSupplier supplier, LlmModel model, OrgVO org, LlmOrgConfig llmOrgConfig) {
+        this.org = org;
+        this.model = model;
+        this.supplier = new LlmSupplierVO(supplier);
+        this.appType = llmOrgConfig.getAppType();
+        this.permitCount = llmOrgConfig.getPermitCount();
+        this.leftCount = llmOrgConfig.getLeftCount();
+    }
+
+    public OrgVO getOrg() {
+        return org;
+    }
+
+    public void setOrg(OrgVO org) {
+        this.org = org;
+    }
+
+    public LlmModel getModel() {
+        return model;
+    }
+
+    public void setModel(LlmModel model) {
+        this.model = model;
+    }
+
+    public LlmSupplierVO getSupplier() {
+        return supplier;
+    }
+
+    public void setSupplier(LlmSupplierVO supplier) {
+        this.supplier = supplier;
+    }
+
+    public LlmAppType getAppType() {
+        return appType;
+    }
+
+    public void setAppType(LlmAppType appType) {
+        this.appType = appType;
+    }
+
+    public int getPermitCount() {
+        return permitCount;
+    }
+
+    public void setPermitCount(int permitCount) {
+        this.permitCount = permitCount;
+    }
+
+    public int getLeftCount() {
+        return leftCount;
+    }
+
+    public void setLeftCount(int leftCount) {
+        this.leftCount = leftCount;
+    }
+}

+ 53 - 0
src/main/java/com/qmth/ops/api/vo/LlmSupplierVO.java

@@ -0,0 +1,53 @@
+package com.qmth.ops.api.vo;
+
+import com.qmth.ops.biz.domain.LlmSupplier;
+
+public class LlmSupplierVO {
+
+    private Long id;
+
+    private String name;
+
+    private Long createTime;
+
+    private Long updateTime;
+
+    public LlmSupplierVO(LlmSupplier supplier) {
+        this.id = supplier.getId();
+        this.name = supplier.getName();
+        this.createTime = supplier.getCreateTime();
+        this.updateTime = supplier.getUpdateTime();
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Long getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Long createTime) {
+        this.createTime = createTime;
+    }
+
+    public Long getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Long updateTime) {
+        this.updateTime = updateTime;
+    }
+}

+ 3 - 3
src/main/java/com/qmth/ops/biz/ai/client/ChatApiClient.java

@@ -21,14 +21,14 @@ public abstract class ChatApiClient {
 
     private ChatApiConfig config;
 
-    private RateLimiter rateLimiter;
+    private RateLimiter queryRateLimiter;
 
     public ChatApiClient(ChatApiConfig config) {
         this.client = new OkHttpClient.Builder().connectionPool(new ConnectionPool()).build();
         this.mapper = new ObjectMapper();
         this.config = config;
         if (config.getQpm() > 0) {
-            this.rateLimiter = new MemoryRateLimiter(config.getQpm(), 60 * 1000);
+            this.queryRateLimiter = new MemoryRateLimiter(config.getQpm(), 60 * 1000);
         }
     }
 
@@ -45,7 +45,7 @@ public abstract class ChatApiClient {
     protected abstract ChatResult handleError(byte[] data, int statusCode, ObjectMapper mapper);
 
     public ChatResult call(ChatRequest request) throws Exception {
-        if (rateLimiter != null && !rateLimiter.acquire()) {
+        if (queryRateLimiter != null && !queryRateLimiter.acquire()) {
             throw new ChatRateLimitExceeded(config.getSupplier(), config.getModel(), config.getQpm());
         }
         RequestBody body = RequestBody

+ 11 - 0
src/main/java/com/qmth/ops/biz/ai/client/ChatApiConfig.java

@@ -15,6 +15,8 @@ public class ChatApiConfig {
 
     private int qpm;
 
+    private int tpm;
+
     public ChatApiConfig() {
 
     }
@@ -25,6 +27,7 @@ public class ChatApiConfig {
         this.secret = supplier.getSecret();
         this.model = model.getName();
         this.qpm = model.getQpm();
+        this.tpm = model.getTpm();
     }
 
     public String getUrl() {
@@ -66,4 +69,12 @@ public class ChatApiConfig {
     public void setQpm(int qpm) {
         this.qpm = qpm;
     }
+
+    public int getTpm() {
+        return tpm;
+    }
+
+    public void setTpm(int tpm) {
+        this.tpm = tpm;
+    }
 }

+ 3 - 0
src/main/java/com/qmth/ops/biz/dao/LlmOrgConfigDao.java

@@ -3,11 +3,14 @@ package com.qmth.ops.biz.dao;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.qmth.boot.core.ai.model.llm.LlmAppType;
 import com.qmth.ops.biz.domain.LlmOrgConfig;
+import com.qmth.ops.biz.query.LlmOrgConfigQuery;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
 public interface LlmOrgConfigDao extends BaseMapper<LlmOrgConfig> {
 
+    LlmOrgConfigQuery findByQuery(LlmOrgConfigQuery query);
+
     @Update("update llm_org_config set left_count=left_count+#{count}, permit_count=permit_count+#{count}"
             + " where org_id=#{orgId} and app_type=#{appType}")
     void permit(@Param("orgId") Long orgId, @Param("appType") LlmAppType appType, @Param("count") int count);

+ 7 - 0
src/main/java/com/qmth/ops/biz/dao/LlmPromptTemplateDao.java

@@ -1,8 +1,15 @@
 package com.qmth.ops.biz.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.qmth.boot.core.ai.model.llm.LlmAppType;
 import com.qmth.ops.biz.domain.LlmPromptTemplate;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
 
 public interface LlmPromptTemplateDao extends BaseMapper<LlmPromptTemplate> {
 
+    @Update("replace into llm_prompt_template (model_id, app_type, system, user) "
+            + "values (#{modelId}, #{appType}, #{system}, #{user})")
+    void replace(@Param("modelId") Long modelId, @Param("appType") LlmAppType appType, @Param("system") String system,
+            @Param("user") String user);
 }

+ 2 - 2
src/main/java/com/qmth/ops/biz/domain/LlmPromptTemplate.java

@@ -10,10 +10,10 @@ public class LlmPromptTemplate implements Serializable {
 
     private static final long serialVersionUID = -2886605312034160681L;
 
-    private LlmAppType appType;
-
     private Long modelId;
 
+    private LlmAppType appType;
+
     private String system;
 
     private String user;

+ 51 - 0
src/main/java/com/qmth/ops/biz/query/LlmOrgConfigQuery.java

@@ -0,0 +1,51 @@
+package com.qmth.ops.biz.query;
+
+import com.qmth.boot.core.ai.model.llm.LlmAppType;
+import com.qmth.boot.mybatis.query.BaseQuery;
+import com.qmth.ops.biz.domain.LlmOrgConfig;
+
+public class LlmOrgConfigQuery extends BaseQuery<LlmOrgConfig> {
+
+    private static final long serialVersionUID = -9177976635952626172L;
+
+    private String orgCode;
+
+    private String orgNameStartWith;
+
+    private LlmAppType appType;
+
+    private Long modelId;
+
+    public String getOrgCode() {
+        return orgCode;
+    }
+
+    public void setOrgCode(String orgCode) {
+        this.orgCode = orgCode;
+    }
+
+    public String getOrgNameStartWith() {
+        return orgNameStartWith;
+    }
+
+    public void setOrgNameStartWith(String orgNameStartWith) {
+        this.orgNameStartWith = orgNameStartWith;
+    }
+
+    public LlmAppType getAppType() {
+        return appType;
+    }
+
+    public void setAppType(LlmAppType appType) {
+        this.appType = appType;
+    }
+
+    public Long getModelId() {
+        return modelId;
+    }
+
+    public void setModelId(Long modelId) {
+        this.modelId = modelId;
+    }
+
+}

+ 13 - 1
src/main/java/com/qmth/ops/biz/service/LlmClientService.java

@@ -29,7 +29,7 @@ public class LlmClientService {
 
     private Map<Long, ChatApiClient> chatApiClientMap = new HashMap<>();
 
-    public void init() {
+    public synchronized void init() {
         List<LlmSupplier> supplierList = supplierService.list();
         for (LlmSupplier supplier : supplierList) {
             List<LlmModel> modelList = modelService.listBySupplier(supplier.getId());
@@ -39,6 +39,18 @@ public class LlmClientService {
         }
     }
 
+    public synchronized void updateBySupplier(LlmSupplier supplier) {
+        List<LlmModel> modelList = modelService.listBySupplier(supplier.getId());
+        for (LlmModel model : modelList) {
+            initChatApiClient(supplier, model);
+        }
+    }
+
+    public synchronized void updateByModel(LlmModel model) {
+        LlmSupplier supplier = supplierService.getById(model.getSupplierId());
+        initChatApiClient(supplier, model);
+    }
+
     private void initChatApiClient(LlmSupplier supplier, LlmModel model) {
         try {
             String className = ChatApiClient.class.getName().replace("ChatApiClient", supplier.getChatClientClass());

+ 10 - 6
src/main/java/com/qmth/ops/biz/service/LlmOrgConfigService.java

@@ -2,12 +2,12 @@ package com.qmth.ops.biz.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.core.ai.model.llm.LlmAppType;
 import com.qmth.ops.biz.dao.LlmOrgConfigDao;
-import com.qmth.ops.biz.domain.LlmModel;
 import com.qmth.ops.biz.domain.LlmOrgConfig;
-import com.qmth.ops.biz.domain.Org;
+import com.qmth.ops.biz.query.LlmOrgConfigQuery;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -19,15 +19,19 @@ public class LlmOrgConfigService extends ServiceImpl<LlmOrgConfigDao, LlmOrgConf
     @Resource
     private LlmOrgConfigDao llmOrgConfigDao;
 
-    public LlmOrgConfig findByOrgAndAppType(Org org, LlmAppType appType) {
-        return llmOrgConfigDao.selectOne(new LambdaQueryWrapper<LlmOrgConfig>().eq(LlmOrgConfig::getOrgId, org.getId())
+    public IPage<LlmOrgConfig> query(LlmOrgConfigQuery query) {
+        return llmOrgConfigDao.findByQuery(query);
+    }
+
+    public LlmOrgConfig findByOrgAndAppType(Long orgId, LlmAppType appType) {
+        return llmOrgConfigDao.selectOne(new LambdaQueryWrapper<LlmOrgConfig>().eq(LlmOrgConfig::getOrgId, orgId)
                 .eq(LlmOrgConfig::getAppType, appType));
     }
 
     @Transactional
-    public void updateModel(LlmOrgConfig llmOrgConfig, LlmModel model) {
+    public void updateModel(LlmOrgConfig llmOrgConfig) {
         llmOrgConfigDao.update(llmOrgConfig,
-                new LambdaUpdateWrapper<LlmOrgConfig>().set(LlmOrgConfig::getModelId, model.getId())
+                new LambdaUpdateWrapper<LlmOrgConfig>().set(LlmOrgConfig::getModelId, llmOrgConfig.getModelId())
                         .eq(LlmOrgConfig::getOrgId, llmOrgConfig.getOrgId())
                         .eq(LlmOrgConfig::getAppType, llmOrgConfig.getAppType()));
     }

+ 22 - 3
src/main/java/com/qmth/ops/biz/service/LlmPromptTemplateService.java

@@ -5,20 +5,39 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.core.ai.model.llm.LlmAppType;
 import com.qmth.ops.biz.dao.LlmPromptTemplateDao;
 import com.qmth.ops.biz.domain.LlmPromptTemplate;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.util.List;
 
 @Service
 public class LlmPromptTemplateService extends ServiceImpl<LlmPromptTemplateDao, LlmPromptTemplate> {
 
+    private static final String CACHE_NAME = "llm_prompt_template";
+
     @Resource
     private LlmPromptTemplateDao llmPromptTemplateDao;
 
-    public LlmPromptTemplate findByAppType(LlmAppType appType, Long modelId) {
+    @Cacheable(value = CACHE_NAME, key = "#modelId+'_'+#appType")
+    public LlmPromptTemplate findByModelAndAppType(Long modelId, LlmAppType appType) {
         return llmPromptTemplateDao.selectOne(
-                new LambdaQueryWrapper<LlmPromptTemplate>().eq(LlmPromptTemplate::getAppType, appType)
-                        .eq(LlmPromptTemplate::getModelId, modelId));
+                new LambdaQueryWrapper<LlmPromptTemplate>().eq(LlmPromptTemplate::getModelId, modelId)
+                        .eq(LlmPromptTemplate::getAppType, appType));
+    }
+
+    public List<LlmPromptTemplate> findByModel(Long modelId) {
+        return llmPromptTemplateDao
+                .selectList(new LambdaQueryWrapper<LlmPromptTemplate>().eq(LlmPromptTemplate::getModelId, modelId));
+    }
+
+    @Transactional
+    @CachePut(value = CACHE_NAME, key = "#template.modelId+'_'+template.appType", unless = "#template==null")
+    public void update(LlmPromptTemplate template) {
+        llmPromptTemplateDao
+                .replace(template.getModelId(), template.getAppType(), template.getSystem(), template.getUser());
     }
 
 }

+ 2 - 1
src/main/java/com/qmth/ops/biz/service/OrgService.java

@@ -1,6 +1,7 @@
 package com.qmth.ops.biz.service;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.ops.biz.dao.OrgDao;
 import com.qmth.ops.biz.domain.Org;
 import com.qmth.ops.biz.query.OrgQuery;
@@ -13,7 +14,7 @@ import java.util.List;
 import java.util.UUID;
 
 @Service
-public class OrgService {
+public class OrgService extends ServiceImpl<OrgDao, Org> {
 
     @Resource
     private OrgDao orgDao;

+ 0 - 1
src/main/resources/application.properties

@@ -1,7 +1,6 @@
 server.port=8080
 ##spring.resources.static-locations=classpath:/static/,file:/Users/luoshi/develop/project/ops-web/,file:/Users/luoshi/develop/data/
 
-##com.qmth.api.global-auth=false
 com.qmth.api.http-trace=true
 
 com.qmth.auth.time-max-ahead=24h

+ 25 - 0
src/main/resources/mapper/LlmOrgConfigMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.qmth.ops.biz.dao.LlmOrgConfigDao">
+
+    <!--MybatisPlus内置规则,开启autoResultMap后,名称为mybatis-plus_XXX-->
+    <select id="findByQuery" resultMap="mybatis-plus_LlmOrgConfig">
+        select c.*
+        from llm_org_config c
+        inner join org g on c.org_id=g.id
+        <where>
+            <if test="orgCode != null">
+                and g.code=#{orgCode}
+            </if>
+            <if test="nameStartWith != null">
+                and g.name like concat(#{nameStartWith},'%')
+            </if>
+            <if test="appType != null">
+                and c.app_type=#{appType}
+            </if>
+            <if test="modelId != null">
+                and c.model_id=#{modelId}
+            </if>
+        </where>
+    </select>
+</mapper>

+ 2 - 2
src/main/resources/script/init.sql

@@ -240,10 +240,10 @@ CREATE TABLE IF NOT EXISTS `llm_org_config`
 
 CREATE TABLE IF NOT EXISTS `llm_prompt_template`
 (
-    `app_type` varchar(32)         NOT NULL,
     `model_id` bigint(20) unsigned NOT NULL,
+    `app_type` varchar(32)         NOT NULL,
     `system`   text                NOT NULL,
     `user`     text                NOT NULL,
-    PRIMARY KEY (`app_type`, `model_id`)
+    PRIMARY KEY (`model_id`, `app_type`)
 ) ENGINE = InnoDB
   DEFAULT CHARSET = utf8mb4;