Commit d3a4c3c7188836b8a6abf8761f73341c4421bb93
Merge branch 'refs/heads/up-master-jdk21-ai' into master-jdk21-ai
# Conflicts: # yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java # yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/DocServiceImpl.java
Showing
18 changed files
with
273 additions
and
17 deletions
yudao-module-ai/pom.xml
| @@ -18,7 +18,7 @@ | @@ -18,7 +18,7 @@ | ||
| 18 | 18 | ||
| 19 | <name>${project.artifactId}</name> | 19 | <name>${project.artifactId}</name> |
| 20 | <description> | 20 | <description> |
| 21 | - ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能。 | 21 | + ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。 |
| 22 | 目前已接入各种模型,不限于: | 22 | 目前已接入各种模型,不限于: |
| 23 | 国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek | 23 | 国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek |
| 24 | 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno | 24 | 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno |
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java
| @@ -22,7 +22,7 @@ public enum AiChatRoleEnum implements IntArrayValuable { | @@ -22,7 +22,7 @@ public enum AiChatRoleEnum implements IntArrayValuable { | ||
| 22 | 除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。 | 22 | 除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。 |
| 23 | """), | 23 | """), |
| 24 | 24 | ||
| 25 | - AI_MIND_MAP_ROLE(2, "脑图助手", """ | 25 | + AI_MIND_MAP_ROLE(2, "导图助手", """ |
| 26 | 你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子: | 26 | 你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子: |
| 27 | # Geek-AI 助手 | 27 | # Geek-AI 助手 |
| 28 | ## 完整的开源系统 | 28 | ## 完整的开源系统 |
yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java
| @@ -45,11 +45,13 @@ public interface ErrorCodeConstants { | @@ -45,11 +45,13 @@ public interface ErrorCodeConstants { | ||
| 45 | // ========== API 音乐 1-040-006-000 ========== | 45 | // ========== API 音乐 1-040-006-000 ========== |
| 46 | ErrorCode MUSIC_NOT_EXISTS = new ErrorCode(1_022_006_000, "音乐不存在!"); | 46 | ErrorCode MUSIC_NOT_EXISTS = new ErrorCode(1_022_006_000, "音乐不存在!"); |
| 47 | 47 | ||
| 48 | - | ||
| 49 | // ========== API 写作 1-022-007-000 ========== | 48 | // ========== API 写作 1-022-007-000 ========== |
| 50 | ErrorCode WRITE_NOT_EXISTS = new ErrorCode(1_022_007_000, "作文不存在!"); | 49 | ErrorCode WRITE_NOT_EXISTS = new ErrorCode(1_022_007_000, "作文不存在!"); |
| 51 | ErrorCode WRITE_STREAM_ERROR = new ErrorCode(1_022_07_001, "写作生成异常!"); | 50 | ErrorCode WRITE_STREAM_ERROR = new ErrorCode(1_022_07_001, "写作生成异常!"); |
| 52 | 51 | ||
| 52 | + // ========== API 思维导图 1-040-008-000 ========== | ||
| 53 | + ErrorCode MIND_MAP_NOT_EXISTS = new ErrorCode(1_040_008_000, "思维导图不存在!"); | ||
| 54 | + | ||
| 53 | 55 | ||
| 54 | // ========== API 知识库 1-022-008-000 ========== | 56 | // ========== API 知识库 1-022-008-000 ========== |
| 55 | ErrorCode KNOWLEDGE_NOT_EXISTS = new ErrorCode(1_022_008_000, "知识库不存在!"); | 57 | ErrorCode KNOWLEDGE_NOT_EXISTS = new ErrorCode(1_022_008_000, "知识库不存在!"); |
yudao-module-ai/yudao-module-ai-biz/pom.xml
| @@ -12,7 +12,7 @@ | @@ -12,7 +12,7 @@ | ||
| 12 | 12 | ||
| 13 | <name>${project.artifactId}</name> | 13 | <name>${project.artifactId}</name> |
| 14 | <description> | 14 | <description> |
| 15 | - ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维脑图等功能。 | 15 | + ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。 |
| 16 | 目前已接入各种模型,不限于: | 16 | 目前已接入各种模型,不限于: |
| 17 | 国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek | 17 | 国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek |
| 18 | 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno | 18 | 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/AiMindMapController.java
| 1 | package cn.iocoder.yudao.module.ai.controller.admin.mindmap; | 1 | package cn.iocoder.yudao.module.ai.controller.admin.mindmap; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 4 | import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; | 6 | import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; |
| 7 | +import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; | ||
| 5 | import cn.iocoder.yudao.module.ai.service.mindmap.AiMindMapService; | 10 | import cn.iocoder.yudao.module.ai.service.mindmap.AiMindMapService; |
| 6 | import io.swagger.v3.oas.annotations.Operation; | 11 | import io.swagger.v3.oas.annotations.Operation; |
| 12 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 7 | import io.swagger.v3.oas.annotations.tags.Tag; | 13 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 8 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 9 | import jakarta.annotation.security.PermitAll; | 15 | import jakarta.annotation.security.PermitAll; |
| 10 | import jakarta.validation.Valid; | 16 | import jakarta.validation.Valid; |
| 11 | import org.springframework.http.MediaType; | 17 | import org.springframework.http.MediaType; |
| 12 | -import org.springframework.web.bind.annotation.PostMapping; | ||
| 13 | -import org.springframework.web.bind.annotation.RequestBody; | ||
| 14 | -import org.springframework.web.bind.annotation.RequestMapping; | ||
| 15 | -import org.springframework.web.bind.annotation.RestController; | 18 | +import org.springframework.security.access.prepost.PreAuthorize; |
| 19 | +import org.springframework.web.bind.annotation.*; | ||
| 16 | import reactor.core.publisher.Flux; | 20 | import reactor.core.publisher.Flux; |
| 17 | 21 | ||
| 22 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 18 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 23 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 19 | 24 | ||
| 20 | @Tag(name = "管理后台 - AI 思维导图") | 25 | @Tag(name = "管理后台 - AI 思维导图") |
| @@ -26,10 +31,29 @@ public class AiMindMapController { | @@ -26,10 +31,29 @@ public class AiMindMapController { | ||
| 26 | private AiMindMapService mindMapService; | 31 | private AiMindMapService mindMapService; |
| 27 | 32 | ||
| 28 | @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) | 33 | @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) |
| 29 | - @Operation(summary = "脑图生成(流式)", description = "流式返回,响应较快") | 34 | + @Operation(summary = "导图生成(流式)", description = "流式返回,响应较快") |
| 30 | @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 | 35 | @PermitAll // 解决 SSE 最终响应的时候,会被 Access Denied 拦截的问题 |
| 31 | public Flux<CommonResult<String>> generateMindMap(@RequestBody @Valid AiMindMapGenerateReqVO generateReqVO) { | 36 | public Flux<CommonResult<String>> generateMindMap(@RequestBody @Valid AiMindMapGenerateReqVO generateReqVO) { |
| 32 | return mindMapService.generateMindMap(generateReqVO, getLoginUserId()); | 37 | return mindMapService.generateMindMap(generateReqVO, getLoginUserId()); |
| 33 | } | 38 | } |
| 34 | 39 | ||
| 40 | + // ================ 导图管理 ================ | ||
| 41 | + | ||
| 42 | + @DeleteMapping("/delete") | ||
| 43 | + @Operation(summary = "删除思维导图") | ||
| 44 | + @Parameter(name = "id", description = "编号", required = true) | ||
| 45 | + @PreAuthorize("@ss.hasPermission('ai:mind-map:delete')") | ||
| 46 | + public CommonResult<Boolean> deleteMindMap(@RequestParam("id") Long id) { | ||
| 47 | + mindMapService.deleteMindMap(id); | ||
| 48 | + return success(true); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + @GetMapping("/page") | ||
| 52 | + @Operation(summary = "获得思维导图分页") | ||
| 53 | + @PreAuthorize("@ss.hasPermission('ai:mind-map:query')") | ||
| 54 | + public CommonResult<PageResult<AiMindMapRespVO>> getMindMapPage(@Valid AiMindMapPageReqVO pageReqVO) { | ||
| 55 | + PageResult<AiMindMapDO> pageResult = mindMapService.getMindMapPage(pageReqVO); | ||
| 56 | + return success(BeanUtils.toBean(pageResult, AiMindMapRespVO.class)); | ||
| 57 | + } | ||
| 58 | + | ||
| 35 | } | 59 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 9 | + | ||
| 10 | +import java.time.LocalDateTime; | ||
| 11 | + | ||
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 13 | + | ||
| 14 | +@Schema(description = "管理后台 - AI 思维导图分页 Request VO") | ||
| 15 | +@Data | ||
| 16 | +@EqualsAndHashCode(callSuper = true) | ||
| 17 | +@ToString(callSuper = true) | ||
| 18 | +public class AiMindMapPageReqVO extends PageParam { | ||
| 19 | + | ||
| 20 | + @Schema(description = "用户编号", example = "4325") | ||
| 21 | + private Long userId; | ||
| 22 | + | ||
| 23 | + @Schema(description = "生成内容提示", example = "Java 学习路线") | ||
| 24 | + private String prompt; | ||
| 25 | + | ||
| 26 | + @Schema(description = "创建时间") | ||
| 27 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 28 | + private LocalDateTime[] createTime; | ||
| 29 | + | ||
| 30 | +} | ||
| 0 | \ No newline at end of file | 31 | \ No newline at end of file |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - AI 思维导图 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class AiMindMapRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3373") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4325") | ||
| 16 | + private Long userId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "生成内容提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 学习路线") | ||
| 19 | + private String prompt; | ||
| 20 | + | ||
| 21 | + @Schema(description = "生成的思维导图内容") | ||
| 22 | + private String generatedContent; | ||
| 23 | + | ||
| 24 | + @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") | ||
| 25 | + private String platform; | ||
| 26 | + | ||
| 27 | + @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125") | ||
| 28 | + private String model; | ||
| 29 | + | ||
| 30 | + @Schema(description = "错误信息") | ||
| 31 | + private String errorMessage; | ||
| 32 | + | ||
| 33 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 34 | + private LocalDateTime createTime; | ||
| 35 | + | ||
| 36 | +} | ||
| 0 | \ No newline at end of file | 37 | \ No newline at end of file |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java
| 1 | package cn.iocoder.yudao.module.ai.dal.mysql.mindmap; | 1 | package cn.iocoder.yudao.module.ai.dal.mysql.mindmap; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; | ||
| 4 | import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; | 7 | import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; |
| 5 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 9 | ||
| @@ -11,4 +14,13 @@ import org.apache.ibatis.annotations.Mapper; | @@ -11,4 +14,13 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 11 | */ | 14 | */ |
| 12 | @Mapper | 15 | @Mapper |
| 13 | public interface AiMindMapMapper extends BaseMapperX<AiMindMapDO> { | 16 | public interface AiMindMapMapper extends BaseMapperX<AiMindMapDO> { |
| 17 | + | ||
| 18 | + default PageResult<AiMindMapDO> selectPage(AiMindMapPageReqVO reqVO) { | ||
| 19 | + return selectPage(reqVO, new LambdaQueryWrapperX<AiMindMapDO>() | ||
| 20 | + .eqIfPresent(AiMindMapDO::getUserId, reqVO.getUserId()) | ||
| 21 | + .eqIfPresent(AiMindMapDO::getPrompt, reqVO.getPrompt()) | ||
| 22 | + .betweenIfPresent(AiMindMapDO::getCreateTime, reqVO.getCreateTime()) | ||
| 23 | + .orderByDesc(AiMindMapDO::getId)); | ||
| 24 | + } | ||
| 25 | + | ||
| 14 | } | 26 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/mindmap/AiMindMapService.java
| 1 | package cn.iocoder.yudao.module.ai.service.mindmap; | 1 | package cn.iocoder.yudao.module.ai.service.mindmap; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; | 5 | import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; |
| 6 | +import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; | ||
| 5 | import reactor.core.publisher.Flux; | 8 | import reactor.core.publisher.Flux; |
| 6 | 9 | ||
| 7 | /** | 10 | /** |
| @@ -20,4 +23,19 @@ public interface AiMindMapService { | @@ -20,4 +23,19 @@ public interface AiMindMapService { | ||
| 20 | */ | 23 | */ |
| 21 | Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId); | 24 | Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId); |
| 22 | 25 | ||
| 26 | + /** | ||
| 27 | + * 删除思维导图 | ||
| 28 | + * | ||
| 29 | + * @param id 编号 | ||
| 30 | + */ | ||
| 31 | + void deleteMindMap(Long id); | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 获得思维导图分页 | ||
| 35 | + * | ||
| 36 | + * @param pageReqVO 分页查询 | ||
| 37 | + * @return 思维导图分页 | ||
| 38 | + */ | ||
| 39 | + PageResult<AiMindMapDO> getMindMapPage(AiMindMapPageReqVO pageReqVO); | ||
| 40 | + | ||
| 23 | } | 41 | } |
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/mindmap/AiMindMapServiceImpl.java
| @@ -6,9 +6,11 @@ import cn.hutool.core.util.StrUtil; | @@ -6,9 +6,11 @@ import cn.hutool.core.util.StrUtil; | ||
| 6 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | 6 | import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; |
| 7 | import cn.iocoder.yudao.framework.ai.core.util.AiUtils; | 7 | import cn.iocoder.yudao.framework.ai.core.util.AiUtils; |
| 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 9 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 9 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 10 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 10 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | 11 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; |
| 11 | import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; | 12 | import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; |
| 13 | +import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; | ||
| 12 | import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; | 14 | import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; |
| 13 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | 15 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; |
| 14 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; | 16 | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; |
| @@ -33,8 +35,10 @@ import reactor.core.publisher.Flux; | @@ -33,8 +35,10 @@ import reactor.core.publisher.Flux; | ||
| 33 | import java.util.ArrayList; | 35 | import java.util.ArrayList; |
| 34 | import java.util.List; | 36 | import java.util.List; |
| 35 | 37 | ||
| 38 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 36 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; | 39 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error; |
| 37 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 40 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 41 | +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.MIND_MAP_NOT_EXISTS; | ||
| 38 | 42 | ||
| 39 | /** | 43 | /** |
| 40 | * AI 思维导图 Service 实现类 | 44 | * AI 思维导图 Service 实现类 |
| @@ -57,10 +61,10 @@ public class AiMindMapServiceImpl implements AiMindMapService { | @@ -57,10 +61,10 @@ public class AiMindMapServiceImpl implements AiMindMapService { | ||
| 57 | 61 | ||
| 58 | @Override | 62 | @Override |
| 59 | public Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId) { | 63 | public Flux<CommonResult<String>> generateMindMap(AiMindMapGenerateReqVO generateReqVO, Long userId) { |
| 60 | - // 1. 获取脑图模型。尝试获取思维导图助手角色,如果没有则使用默认模型 | 64 | + // 1. 获取导图模型。尝试获取思维导图助手角色,如果没有则使用默认模型 |
| 61 | AiChatRoleDO role = CollUtil.getFirst( | 65 | AiChatRoleDO role = CollUtil.getFirst( |
| 62 | chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_MIND_MAP_ROLE.getName())); | 66 | chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_MIND_MAP_ROLE.getName())); |
| 63 | - // 1.1 获取脑图执行模型 | 67 | + // 1.1 获取导图执行模型 |
| 64 | AiChatModelDO model = getModel(role); | 68 | AiChatModelDO model = getModel(role); |
| 65 | // 1.2 获取角色设定消息 | 69 | // 1.2 获取角色设定消息 |
| 66 | String systemMessage = role != null && StrUtil.isNotBlank(role.getSystemMessage()) | 70 | String systemMessage = role != null && StrUtil.isNotBlank(role.getSystemMessage()) |
| @@ -131,4 +135,23 @@ public class AiMindMapServiceImpl implements AiMindMapService { | @@ -131,4 +135,23 @@ public class AiMindMapServiceImpl implements AiMindMapService { | ||
| 131 | return model; | 135 | return model; |
| 132 | } | 136 | } |
| 133 | 137 | ||
| 138 | + @Override | ||
| 139 | + public void deleteMindMap(Long id) { | ||
| 140 | + // 校验存在 | ||
| 141 | + validateMindMapExists(id); | ||
| 142 | + // 删除 | ||
| 143 | + mindMapMapper.deleteById(id); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + private void validateMindMapExists(Long id) { | ||
| 147 | + if (mindMapMapper.selectById(id) == null) { | ||
| 148 | + throw exception(MIND_MAP_NOT_EXISTS); | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + @Override | ||
| 153 | + public PageResult<AiMindMapDO> getMindMapPage(AiMindMapPageReqVO pageReqVO) { | ||
| 154 | + return mindMapMapper.selectPage(pageReqVO); | ||
| 155 | + } | ||
| 156 | + | ||
| 134 | } | 157 | } |
yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
| @@ -23,7 +23,6 @@ | @@ -23,7 +23,6 @@ | ||
| 23 | <artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId> | 23 | <artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId> |
| 24 | <version>${spring-ai.version}</version> | 24 | <version>${spring-ai.version}</version> |
| 25 | </dependency> | 25 | </dependency> |
| 26 | - | ||
| 27 | <dependency> | 26 | <dependency> |
| 28 | <groupId>org.springframework.ai</groupId> | 27 | <groupId>org.springframework.ai</groupId> |
| 29 | <artifactId>spring-ai-openai-spring-boot-starter</artifactId> | 28 | <artifactId>spring-ai-openai-spring-boot-starter</artifactId> |
| @@ -31,6 +30,11 @@ | @@ -31,6 +30,11 @@ | ||
| 31 | </dependency> | 30 | </dependency> |
| 32 | <dependency> | 31 | <dependency> |
| 33 | <groupId>org.springframework.ai</groupId> | 32 | <groupId>org.springframework.ai</groupId> |
| 33 | + <artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId> | ||
| 34 | + <version>${spring-ai.version}</version> | ||
| 35 | + </dependency> | ||
| 36 | + <dependency> | ||
| 37 | + <groupId>org.springframework.ai</groupId> | ||
| 34 | <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> | 38 | <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> |
| 35 | <version>${spring-ai.version}</version> | 39 | <version>${spring-ai.version}</version> |
| 36 | </dependency> | 40 | </dependency> |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/config/YudaoAiAutoConfiguration.java
| @@ -12,6 +12,7 @@ import com.alibaba.cloud.ai.tongyi.TongYiAutoConfiguration; | @@ -12,6 +12,7 @@ import com.alibaba.cloud.ai.tongyi.TongYiAutoConfiguration; | ||
| 12 | import lombok.extern.slf4j.Slf4j; | 12 | import lombok.extern.slf4j.Slf4j; |
| 13 | import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; | 13 | import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; |
| 14 | import org.springframework.ai.document.MetadataMode; | 14 | import org.springframework.ai.document.MetadataMode; |
| 15 | +import org.springframework.ai.embedding.EmbeddingModel; | ||
| 15 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; | 16 | import org.springframework.ai.transformer.splitter.TokenTextSplitter; |
| 16 | import org.springframework.ai.transformers.TransformersEmbeddingModel; | 17 | import org.springframework.ai.transformers.TransformersEmbeddingModel; |
| 17 | import org.springframework.ai.vectorstore.RedisVectorStore; | 18 | import org.springframework.ai.vectorstore.RedisVectorStore; |
| @@ -21,6 +22,7 @@ import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | @@ -21,6 +22,7 @@ import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | ||
| 21 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 22 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 22 | import org.springframework.context.annotation.Bean; | 23 | import org.springframework.context.annotation.Bean; |
| 23 | import org.springframework.context.annotation.Import; | 24 | import org.springframework.context.annotation.Import; |
| 25 | +import org.springframework.context.annotation.Lazy; | ||
| 24 | import redis.clients.jedis.JedisPooled; | 26 | import redis.clients.jedis.JedisPooled; |
| 25 | 27 | ||
| 26 | /** | 28 | /** |
| @@ -82,7 +84,8 @@ public class YudaoAiAutoConfiguration { | @@ -82,7 +84,8 @@ public class YudaoAiAutoConfiguration { | ||
| 82 | 84 | ||
| 83 | // ========== rag 相关 ========== | 85 | // ========== rag 相关 ========== |
| 84 | @Bean | 86 | @Bean |
| 85 | - public TransformersEmbeddingModel transformersEmbeddingClient() { | 87 | + @Lazy // TODO 芋艿:临时注释,避免无法启动 |
| 88 | + public EmbeddingModel transformersEmbeddingClient() { | ||
| 86 | return new TransformersEmbeddingModel(MetadataMode.EMBED); | 89 | return new TransformersEmbeddingModel(MetadataMode.EMBED); |
| 87 | } | 90 | } |
| 88 | 91 | ||
| @@ -90,6 +93,7 @@ public class YudaoAiAutoConfiguration { | @@ -90,6 +93,7 @@ public class YudaoAiAutoConfiguration { | ||
| 90 | * 我们启动有加载很多 Embedding 模型,不晓得取哪个好,先 new 个 TransformersEmbeddingModel 跑 | 93 | * 我们启动有加载很多 Embedding 模型,不晓得取哪个好,先 new 个 TransformersEmbeddingModel 跑 |
| 91 | */ | 94 | */ |
| 92 | @Bean | 95 | @Bean |
| 96 | + @Lazy // TODO 芋艿:临时注释,避免无法启动 | ||
| 93 | public RedisVectorStore vectorStore(TransformersEmbeddingModel transformersEmbeddingModel, RedisVectorStoreProperties properties, | 97 | public RedisVectorStore vectorStore(TransformersEmbeddingModel transformersEmbeddingModel, RedisVectorStoreProperties properties, |
| 94 | RedisProperties redisProperties) { | 98 | RedisProperties redisProperties) { |
| 95 | var config = RedisVectorStore.RedisVectorStoreConfig.builder() | 99 | var config = RedisVectorStore.RedisVectorStoreConfig.builder() |
| @@ -105,6 +109,7 @@ public class YudaoAiAutoConfiguration { | @@ -105,6 +109,7 @@ public class YudaoAiAutoConfiguration { | ||
| 105 | } | 109 | } |
| 106 | 110 | ||
| 107 | @Bean | 111 | @Bean |
| 112 | + @Lazy // TODO 芋艿:临时注释,避免无法启动 | ||
| 108 | public TokenTextSplitter tokenTextSplitter() { | 113 | public TokenTextSplitter tokenTextSplitter() { |
| 109 | return new TokenTextSplitter(500, 100, 5, 10000, true); | 114 | return new TokenTextSplitter(500, 100, 5, 10000, true); |
| 110 | } | 115 | } |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/enums/AiPlatformEnum.java
| @@ -22,7 +22,8 @@ public enum AiPlatformEnum { | @@ -22,7 +22,8 @@ public enum AiPlatformEnum { | ||
| 22 | 22 | ||
| 23 | // ========== 国外平台 ========== | 23 | // ========== 国外平台 ========== |
| 24 | 24 | ||
| 25 | - OPENAI("OpenAI", "OpenAI"), | 25 | + OPENAI("OpenAI", "OpenAI"), // OpenAI 官方 |
| 26 | + AZURE_OPENAI("AzureOpenAI", "AzureOpenAI"), // OpenAI 微软 | ||
| 26 | OLLAMA("Ollama", "Ollama"), | 27 | OLLAMA("Ollama", "Ollama"), |
| 27 | 28 | ||
| 28 | STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI | 29 | STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/factory/AiModelFactoryImpl.java
| @@ -21,6 +21,10 @@ import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel; | @@ -21,6 +21,10 @@ import com.alibaba.cloud.ai.tongyi.image.TongYiImagesModel; | ||
| 21 | import com.alibaba.cloud.ai.tongyi.image.TongYiImagesProperties; | 21 | import com.alibaba.cloud.ai.tongyi.image.TongYiImagesProperties; |
| 22 | import com.alibaba.dashscope.aigc.generation.Generation; | 22 | import com.alibaba.dashscope.aigc.generation.Generation; |
| 23 | import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis; | 23 | import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis; |
| 24 | +import com.azure.ai.openai.OpenAIClient; | ||
| 25 | +import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; | ||
| 26 | +import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties; | ||
| 27 | +import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties; | ||
| 24 | import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; | 28 | import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; |
| 25 | import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; | 29 | import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; |
| 26 | import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; | 30 | import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; |
| @@ -31,6 +35,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; | @@ -31,6 +35,7 @@ import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; | ||
| 31 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties; | 35 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiChatProperties; |
| 32 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; | 36 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiConnectionProperties; |
| 33 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiImageProperties; | 37 | import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiImageProperties; |
| 38 | +import org.springframework.ai.azure.openai.AzureOpenAiChatModel; | ||
| 34 | import org.springframework.ai.chat.model.ChatModel; | 39 | import org.springframework.ai.chat.model.ChatModel; |
| 35 | import org.springframework.ai.image.ImageModel; | 40 | import org.springframework.ai.image.ImageModel; |
| 36 | import org.springframework.ai.model.function.FunctionCallbackContext; | 41 | import org.springframework.ai.model.function.FunctionCallbackContext; |
| @@ -82,6 +87,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -82,6 +87,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 82 | return buildXingHuoChatModel(apiKey); | 87 | return buildXingHuoChatModel(apiKey); |
| 83 | case OPENAI: | 88 | case OPENAI: |
| 84 | return buildOpenAiChatModel(apiKey, url); | 89 | return buildOpenAiChatModel(apiKey, url); |
| 90 | + case AZURE_OPENAI: | ||
| 91 | + return buildAzureOpenAiChatModel(apiKey, url); | ||
| 85 | case OLLAMA: | 92 | case OLLAMA: |
| 86 | return buildOllamaChatModel(url); | 93 | return buildOllamaChatModel(url); |
| 87 | default: | 94 | default: |
| @@ -106,6 +113,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -106,6 +113,8 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 106 | return SpringUtil.getBean(XingHuoChatModel.class); | 113 | return SpringUtil.getBean(XingHuoChatModel.class); |
| 107 | case OPENAI: | 114 | case OPENAI: |
| 108 | return SpringUtil.getBean(OpenAiChatModel.class); | 115 | return SpringUtil.getBean(OpenAiChatModel.class); |
| 116 | + case AZURE_OPENAI: | ||
| 117 | + return SpringUtil.getBean(AzureOpenAiChatModel.class); | ||
| 109 | case OLLAMA: | 118 | case OLLAMA: |
| 110 | return SpringUtil.getBean(OllamaChatModel.class); | 119 | return SpringUtil.getBean(OllamaChatModel.class); |
| 111 | default: | 120 | default: |
| @@ -269,6 +278,21 @@ public class AiModelFactoryImpl implements AiModelFactory { | @@ -269,6 +278,21 @@ public class AiModelFactoryImpl implements AiModelFactory { | ||
| 269 | } | 278 | } |
| 270 | 279 | ||
| 271 | /** | 280 | /** |
| 281 | + * 可参考 {@link AzureOpenAiAutoConfiguration} | ||
| 282 | + */ | ||
| 283 | + private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) { | ||
| 284 | + AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration(); | ||
| 285 | + // 创建 OpenAIClient 对象 | ||
| 286 | + AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties(); | ||
| 287 | + connectionProperties.setApiKey(apiKey); | ||
| 288 | + connectionProperties.setEndpoint(url); | ||
| 289 | + OpenAIClient openAIClient = azureOpenAiAutoConfiguration.openAIClient(connectionProperties); | ||
| 290 | + // 获取 AzureOpenAiChatProperties 对象 | ||
| 291 | + AzureOpenAiChatProperties chatProperties = SpringUtil.getBean(AzureOpenAiChatProperties.class); | ||
| 292 | + return azureOpenAiAutoConfiguration.azureOpenAiChatModel(openAIClient, chatProperties, null, null); | ||
| 293 | + } | ||
| 294 | + | ||
| 295 | + /** | ||
| 272 | * 可参考 {@link OpenAiAutoConfiguration} | 296 | * 可参考 {@link OpenAiAutoConfiguration} |
| 273 | */ | 297 | */ |
| 274 | private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { | 298 | private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { |
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
| @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; | ||
| 5 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions; | 5 | import cn.iocoder.yudao.framework.ai.core.model.deepseek.DeepSeekChatOptions; |
| 6 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatOptions; | 6 | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatOptions; |
| 7 | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions; | 7 | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions; |
| 8 | +import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; | ||
| 8 | import org.springframework.ai.chat.messages.*; | 9 | import org.springframework.ai.chat.messages.*; |
| 9 | import org.springframework.ai.chat.prompt.ChatOptions; | 10 | import org.springframework.ai.chat.prompt.ChatOptions; |
| 10 | import org.springframework.ai.ollama.api.OllamaOptions; | 11 | import org.springframework.ai.ollama.api.OllamaOptions; |
| @@ -35,6 +36,9 @@ public class AiUtils { | @@ -35,6 +36,9 @@ public class AiUtils { | ||
| 35 | return XingHuoChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build(); | 36 | return XingHuoChatOptions.builder().model(model).temperature(temperatureF).maxTokens(maxTokens).build(); |
| 36 | case OPENAI: | 37 | case OPENAI: |
| 37 | return OpenAiChatOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build(); | 38 | return OpenAiChatOptions.builder().withModel(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build(); |
| 39 | + case AZURE_OPENAI: | ||
| 40 | + // TODO 芋艿:貌似没 model 字段???! | ||
| 41 | + return AzureOpenAiChatOptions.builder().withDeploymentName(model).withTemperature(temperatureF).withMaxTokens(maxTokens).build(); | ||
| 38 | case OLLAMA: | 42 | case OLLAMA: |
| 39 | return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens); | 43 | return OllamaOptions.create().withModel(model).withTemperature(temperatureF).withNumPredict(maxTokens); |
| 40 | default: | 44 | default: |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/AzureOpenAIChatModelTests.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.ai.chat; | ||
| 2 | + | ||
| 3 | +import com.azure.ai.openai.OpenAIClient; | ||
| 4 | +import com.azure.ai.openai.OpenAIClientBuilder; | ||
| 5 | +import com.azure.core.credential.AzureKeyCredential; | ||
| 6 | +import com.azure.core.util.ClientOptions; | ||
| 7 | +import org.junit.jupiter.api.Disabled; | ||
| 8 | +import org.junit.jupiter.api.Test; | ||
| 9 | +import org.springframework.ai.azure.openai.AzureOpenAiChatModel; | ||
| 10 | +import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; | ||
| 11 | +import org.springframework.ai.chat.messages.Message; | ||
| 12 | +import org.springframework.ai.chat.messages.SystemMessage; | ||
| 13 | +import org.springframework.ai.chat.messages.UserMessage; | ||
| 14 | +import org.springframework.ai.chat.model.ChatResponse; | ||
| 15 | +import org.springframework.ai.chat.prompt.Prompt; | ||
| 16 | +import reactor.core.publisher.Flux; | ||
| 17 | + | ||
| 18 | +import java.util.ArrayList; | ||
| 19 | +import java.util.List; | ||
| 20 | + | ||
| 21 | +import static org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * {@link AzureOpenAiChatModel} 集成测试 | ||
| 25 | + * | ||
| 26 | + * @author 芋道源码 | ||
| 27 | + */ | ||
| 28 | +public class AzureOpenAIChatModelTests { | ||
| 29 | + | ||
| 30 | + private final OpenAIClient openAiApi = (new OpenAIClientBuilder()) | ||
| 31 | + .endpoint("https://eastusprejade.openai.azure.com") | ||
| 32 | + .credential(new AzureKeyCredential("xxx")) | ||
| 33 | + .clientOptions((new ClientOptions()).setApplicationId("spring-ai")) | ||
| 34 | + .buildClient(); | ||
| 35 | + private final AzureOpenAiChatModel chatModel = new AzureOpenAiChatModel(openAiApi, | ||
| 36 | + AzureOpenAiChatOptions.builder().withDeploymentName(DEFAULT_DEPLOYMENT_NAME).build()); | ||
| 37 | + | ||
| 38 | + @Test | ||
| 39 | + @Disabled | ||
| 40 | + public void testCall() { | ||
| 41 | + // 准备参数 | ||
| 42 | + List<Message> messages = new ArrayList<>(); | ||
| 43 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 44 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 45 | + | ||
| 46 | + // 调用 | ||
| 47 | + ChatResponse response = chatModel.call(new Prompt(messages)); | ||
| 48 | + // 打印结果 | ||
| 49 | + System.out.println(response); | ||
| 50 | + System.out.println(response.getResult().getOutput()); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @Test | ||
| 54 | + @Disabled | ||
| 55 | + public void testStream() { | ||
| 56 | + // 准备参数 | ||
| 57 | + List<Message> messages = new ArrayList<>(); | ||
| 58 | + messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); | ||
| 59 | + messages.add(new UserMessage("1 + 1 = ?")); | ||
| 60 | + | ||
| 61 | + // 调用 | ||
| 62 | + Flux<ChatResponse> flux = chatModel.stream(new Prompt(messages)); | ||
| 63 | + // 打印结果 | ||
| 64 | + flux.doOnNext(response -> { | ||
| 65 | +// System.out.println(response); | ||
| 66 | + System.out.println(response.getResult().getOutput()); | ||
| 67 | + }).then().block(); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | +} |
yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/chat/OpenAIChatModelTests.java
| 1 | package cn.iocoder.yudao.framework.ai.chat; | 1 | package cn.iocoder.yudao.framework.ai.chat; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; | ||
| 4 | import org.junit.jupiter.api.Disabled; | 3 | import org.junit.jupiter.api.Disabled; |
| 5 | import org.junit.jupiter.api.Test; | 4 | import org.junit.jupiter.api.Test; |
| 6 | import org.springframework.ai.chat.messages.Message; | 5 | import org.springframework.ai.chat.messages.Message; |
| @@ -17,7 +16,7 @@ import java.util.ArrayList; | @@ -17,7 +16,7 @@ import java.util.ArrayList; | ||
| 17 | import java.util.List; | 16 | import java.util.List; |
| 18 | 17 | ||
| 19 | /** | 18 | /** |
| 20 | - * {@link XingHuoChatModel} 集成测试 | 19 | + * {@link OpenAiChatModel} 集成测试 |
| 21 | * | 20 | * |
| 22 | * @author 芋道源码 | 21 | * @author 芋道源码 |
| 23 | */ | 22 | */ |
yudao-server/src/main/resources/application.yaml
| @@ -162,9 +162,13 @@ spring: | @@ -162,9 +162,13 @@ spring: | ||
| 162 | secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK | 162 | secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK |
| 163 | zhipuai: # 智谱 AI | 163 | zhipuai: # 智谱 AI |
| 164 | api-key: 32f84543e54eee31f8d56b2bd6020573.3vh9idLJZ2ZhxDEs | 164 | api-key: 32f84543e54eee31f8d56b2bd6020573.3vh9idLJZ2ZhxDEs |
| 165 | - openai: | 165 | + openai: # OpenAI 官方 |
| 166 | api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z | 166 | api-key: sk-yzKea6d8e8212c3bdd99f9f44ced1cae37c097e5aa3BTS7z |
| 167 | base-url: https://api.gptsapi.net | 167 | base-url: https://api.gptsapi.net |
| 168 | + azure: # OpenAI 微软 | ||
| 169 | + openai: | ||
| 170 | + endpoint: https://eastusprejade.openai.azure.com | ||
| 171 | + api-key: xxx | ||
| 168 | ollama: | 172 | ollama: |
| 169 | base-url: http://127.0.0.1:11434 | 173 | base-url: http://127.0.0.1:11434 |
| 170 | chat: | 174 | chat: |