tik集成
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -15,7 +15,7 @@
|
|||||||
<!-- 各种 module 拓展 -->
|
<!-- 各种 module 拓展 -->
|
||||||
<module>yudao-module-system</module>
|
<module>yudao-module-system</module>
|
||||||
<module>yudao-module-infra</module>
|
<module>yudao-module-infra</module>
|
||||||
<!-- <module>yudao-module-member</module>-->
|
<module>yudao-module-member</module>
|
||||||
<!-- <module>yudao-module-bpm</module>-->
|
<!-- <module>yudao-module-bpm</module>-->
|
||||||
<!-- <module>yudao-module-report</module>-->
|
<!-- <module>yudao-module-report</module>-->
|
||||||
<!-- <module>yudao-module-mp</module>-->
|
<!-- <module>yudao-module-mp</module>-->
|
||||||
|
|||||||
@@ -149,6 +149,43 @@
|
|||||||
<version>${alibaba-ai.version}</version>
|
<version>${alibaba-ai.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>dashscope-sdk-java</artifactId>
|
||||||
|
<version>2.21.11</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.github.victools</groupId>
|
||||||
|
<artifactId>jsonschema-generator</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<!-- 排除 SDK 自带的 OkHttp 和 Okio -->
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.12.0</version> <!-- 使用较新的稳定版本 -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>3.8.0</version> <!-- 与 OkHttp 4.12.0 严格兼容 -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 3. 引入 Kotlin 运行时(OkHttp 4.x+ 必须) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-stdlib</artifactId>
|
||||||
|
<version>1.9.20</version> <!-- 与 OkHttp 4.12.0 兼容的版本 -->
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- 文心一言 -->
|
<!-- 文心一言 -->
|
||||||
<groupId>org.springaicommunity</groupId>
|
<groupId>org.springaicommunity</groupId>
|
||||||
|
|||||||
@@ -1,10 +1,23 @@
|
|||||||
package cn.iocoder.yudao.module.ai.controller.admin.tikhup;
|
package cn.iocoder.yudao.module.ai.controller.admin.tikhup;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.ai.dal.mysql.tikhup.TikPromptMapper;
|
||||||
import cn.iocoder.yudao.module.ai.service.tikhup.TikHupService;
|
import cn.iocoder.yudao.module.ai.service.tikhup.TikHupService;
|
||||||
|
import com.alibaba.dashscope.app.Application;
|
||||||
|
import com.alibaba.dashscope.app.ApplicationParam;
|
||||||
|
import com.alibaba.dashscope.app.ApplicationResult;
|
||||||
|
import com.alibaba.dashscope.app.FlowStreamMode;
|
||||||
|
import com.alibaba.dashscope.utils.Constants;
|
||||||
|
import com.alibaba.dashscope.utils.JsonUtils;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import io.reactivex.Flowable;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -13,10 +26,13 @@ import java.util.Map;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/ai/tikHup")
|
@RequestMapping("/ai/tikHup")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
public class TikHupController {
|
public class TikHupController {
|
||||||
|
|
||||||
private final TikHupService tikHupService;
|
private final TikHupService tikHupService;
|
||||||
|
|
||||||
|
private final TikPromptMapper tikPromptMapper;
|
||||||
|
|
||||||
@GetMapping("/fetch_user_post_videos")
|
@GetMapping("/fetch_user_post_videos")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "获取用户主页作品数据",
|
summary = "获取用户主页作品数据",
|
||||||
@@ -44,4 +60,68 @@ public class TikHupController {
|
|||||||
return tikHupService.videoToCharacters2(fileLinkList);
|
return tikHupService.videoToCharacters2(fileLinkList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/getPromptTypeList")
|
||||||
|
@Operation(summary = "获取提示词类型列表", description = "获取提示词类型列表")
|
||||||
|
public Object getPromptTypeList(){
|
||||||
|
return CommonResult.success(tikPromptMapper.getTikPromptVOList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/deepseekAnalysis")
|
||||||
|
@Operation(summary = "deepseek文案重写", description = "deepseek文案重写")
|
||||||
|
public Object deepseekAnalysis(@RequestBody Map<String,Object> contentMap){
|
||||||
|
String content = (String) contentMap.get("content");
|
||||||
|
String promptType = (String) contentMap.get("promptType");
|
||||||
|
return tikHupService.deepseekAnalysis(promptType,content);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/callWorkflow")
|
||||||
|
@Operation(summary = "调用阿里工作流", description = "调用阿里工作流 文档地址:https://help.aliyun.com/zh/model-studio/invoke-workflow-application?mode=pure#8f4b4d2ce9fry")
|
||||||
|
public Flux<String> callWorkflow(@RequestBody Map<String,Object> params){
|
||||||
|
Constants.baseHttpApiUrl = "https://dashscope.aliyuncs.com/api/v1";
|
||||||
|
ApplicationParam param = ApplicationParam.builder()
|
||||||
|
// 若没有配置环境变量,可用百炼API Key将下行替换为:.apiKey("sk-xxx")。但不建议在生产环境中直接将API Key硬编码到代码中,以减少API Key泄露风险。
|
||||||
|
.apiKey("sk-10c746f8cb8640738f8d6b71af699003")
|
||||||
|
.appId("bb746b74bfb0439e841cb309dc9f945c")
|
||||||
|
.flowStreamMode(FlowStreamMode.MESSAGE_FORMAT)
|
||||||
|
.bizParams(JsonUtils.parse(JSON.toJSONString(params)))
|
||||||
|
.prompt((String) params.get("audio_prompt"))
|
||||||
|
.hasThoughts(false)
|
||||||
|
.incrementalOutput(true)
|
||||||
|
.build();
|
||||||
|
Application application = new Application();
|
||||||
|
try{
|
||||||
|
//ApplicationResult result = application.call(param);
|
||||||
|
//return CommonResult.success(result.getOutput().getText());
|
||||||
|
Flowable<ApplicationResult> flowableResult = application.streamCall(param);
|
||||||
|
// 关键:RxJava Flowable 转 WebFlux Flux,指定非阻塞线程调度
|
||||||
|
// 4.2 将 RxJava Flowable 转换为 WebFlux Flux(响应式转换,无阻塞)
|
||||||
|
return Flux.from(flowableResult)
|
||||||
|
// 关键:切换到非阻塞线程执行(避免阻塞 WebFlux 事件循环)
|
||||||
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
|
// 4.3 处理每一条流式数据:提取 thoughts 字段(按你的需求,也可提取 text)
|
||||||
|
.map(applicationResult -> {
|
||||||
|
// 校验结果非 null(阿里 SDK 可能返回空结果)
|
||||||
|
if (applicationResult == null || applicationResult.getOutput() == null) {
|
||||||
|
log.warn("收到空的流式结果");
|
||||||
|
return "空结果";
|
||||||
|
}
|
||||||
|
return applicationResult.getOutput().getWorkflowMessage().getMessage().getContent();
|
||||||
|
})
|
||||||
|
// 4.4 流处理异常捕获(如网络中断、阿里 SDK 内部错误)
|
||||||
|
.onErrorMap(e -> {
|
||||||
|
log.error("流式处理异常", e); // 打印完整异常栈,便于排查
|
||||||
|
return new RuntimeException("流式处理错误:" + e.getMessage());
|
||||||
|
})
|
||||||
|
// 4.5 异常时返回默认提示(前端不会断连,而是接收错误信息)
|
||||||
|
.onErrorReturn("错误:流式处理中断:" + "请重试或联系管理员");
|
||||||
|
}catch (Exception e){
|
||||||
|
// 捕获 SDK 调用时的同步异常(如初始化失败、网络连接超时)
|
||||||
|
log.error("调用阿里 SDK 失败", e);
|
||||||
|
return Flux.just("错误:SDK 调用失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@TableName("tik_prompt")
|
||||||
|
@Data
|
||||||
|
public class TikPromptVO {
|
||||||
|
|
||||||
|
@TableField(value = "prompt_type")
|
||||||
|
private String promptType;
|
||||||
|
|
||||||
|
@TableField(value = "prompt_name")
|
||||||
|
private String promptName;
|
||||||
|
|
||||||
|
@TableField(value = "prompt")
|
||||||
|
private String prompt;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,29 +2,15 @@ package cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Schema(description = "TikToken - TikToken管理 Request VO")
|
|
||||||
@TableName("tik_token")
|
@TableName("tik_token")
|
||||||
@Data
|
@Data
|
||||||
public class TikTokenVO {
|
public class TikTokenVO {
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "TikHup平台API地址",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED,
|
|
||||||
example = "https://api.tikhub.io/api/v1/xiaohongshu/app/get_user_info",
|
|
||||||
title = "平台API地址"
|
|
||||||
)
|
|
||||||
@TableField(value = "platform_url")
|
@TableField(value = "platform_url")
|
||||||
private String platformUrl;
|
private String platformUrl;
|
||||||
|
|
||||||
@Schema(
|
|
||||||
description = "TikHup平台访问Token,用于API认证",
|
|
||||||
requiredMode = Schema.RequiredMode.REQUIRED,
|
|
||||||
example = "y15aJOgphU+dik4QGaCW3CL2bR7eQ6ZA2Tz3tUe8c6ycoW27OX+zRTO6Ow==",
|
|
||||||
title = "平台访问Token"
|
|
||||||
)
|
|
||||||
@TableField(value = "platform_token")
|
@TableField(value = "platform_token")
|
||||||
private String platformToken;
|
private String platformToken;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.iocoder.yudao.module.ai.dal.mysql.tikhup;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo.TikPromptVO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface TikPromptMapper extends BaseMapperX<TikPromptVO> {
|
||||||
|
|
||||||
|
default TikPromptVO getTikPromptVO(String promptType) {
|
||||||
|
return selectOne("prompt_type",promptType);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<TikPromptVO> getTikPromptVOList() {
|
||||||
|
return selectList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo.TikTokenVO;
|
|||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface TikHupMapper extends BaseMapperX<TikTokenVO> {
|
public interface TikTokenMapper extends BaseMapperX<TikTokenVO> {
|
||||||
|
|
||||||
default TikTokenVO getPlatformToken(String platformUrl) {
|
default TikTokenVO getPlatformToken(String platformUrl) {
|
||||||
return selectOne("platform_url",platformUrl);
|
return selectOne("platform_url",platformUrl);
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package cn.iocoder.yudao.module.ai.service.tikhup;
|
package cn.iocoder.yudao.module.ai.service.tikhup;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface TikHupService {
|
public interface TikHupService {
|
||||||
|
|
||||||
@@ -27,4 +30,12 @@ public interface TikHupService {
|
|||||||
*/
|
*/
|
||||||
Object videoToCharacters2(List<String> fileLinkList);
|
Object videoToCharacters2(List<String> fileLinkList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param promptType 提示词类型
|
||||||
|
* @param content 提示词内容
|
||||||
|
* @return deepseek改写后的内容
|
||||||
|
*/
|
||||||
|
Object deepseekAnalysis(String promptType,String content);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package cn.iocoder.yudao.module.ai.service.tikhup;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
|
import cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo.TikPromptVO;
|
||||||
import cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo.TikTokenVO;
|
import cn.iocoder.yudao.module.ai.controller.admin.tikhup.vo.TikTokenVO;
|
||||||
import cn.iocoder.yudao.module.ai.dal.mysql.tikhup.TikHupMapper;
|
import cn.iocoder.yudao.module.ai.dal.mysql.tikhup.TikPromptMapper;
|
||||||
|
import cn.iocoder.yudao.module.ai.dal.mysql.tikhup.TikTokenMapper;
|
||||||
import com.alibaba.dashscope.audio.asr.transcription.Transcription;
|
import com.alibaba.dashscope.audio.asr.transcription.Transcription;
|
||||||
import com.alibaba.dashscope.audio.asr.transcription.TranscriptionParam;
|
import com.alibaba.dashscope.audio.asr.transcription.TranscriptionParam;
|
||||||
import com.alibaba.dashscope.audio.asr.transcription.TranscriptionQueryParam;
|
import com.alibaba.dashscope.audio.asr.transcription.TranscriptionQueryParam;
|
||||||
@@ -25,7 +27,9 @@ import java.util.List;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TikHupServiceImpl implements TikHupService{
|
public class TikHupServiceImpl implements TikHupService{
|
||||||
|
|
||||||
private final TikHupMapper tikHupMapper;
|
private final TikTokenMapper tikTokenMapper;
|
||||||
|
|
||||||
|
private final TikPromptMapper tikPromptMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object fetch_user_post_videos(String type,String sec_user_id, int max_cursor, int count){
|
public Object fetch_user_post_videos(String type,String sec_user_id, int max_cursor, int count){
|
||||||
@@ -37,7 +41,7 @@ public class TikHupServiceImpl implements TikHupService{
|
|||||||
} else if("tik-app".equals(type)){
|
} else if("tik-app".equals(type)){
|
||||||
url = "https://api.tikhub.io/api/v1/douyin/app/v3/fetch_user_post_videos";
|
url = "https://api.tikhub.io/api/v1/douyin/app/v3/fetch_user_post_videos";
|
||||||
}
|
}
|
||||||
TikTokenVO tikTokenVO = tikHupMapper.getPlatformToken(url);
|
TikTokenVO tikTokenVO = tikTokenMapper.getPlatformToken(url);
|
||||||
String Authorization = tikTokenVO.getPlatformToken();
|
String Authorization = tikTokenVO.getPlatformToken();
|
||||||
try{
|
try{
|
||||||
Unirest.setTimeouts(0, 0);
|
Unirest.setTimeouts(0, 0);
|
||||||
@@ -57,6 +61,7 @@ public class TikHupServiceImpl implements TikHupService{
|
|||||||
private final String appKey = "sldJ4XSpYp3rKALZ ";
|
private final String appKey = "sldJ4XSpYp3rKALZ ";
|
||||||
private final String accessKeyId = "LTAI5tPV9Ag3csf41GZjaLTA";
|
private final String accessKeyId = "LTAI5tPV9Ag3csf41GZjaLTA";
|
||||||
private final String accessKeySecret = "kDqlGeJTKw6tJtFYiaY8vQTFuVIQDs";
|
private final String accessKeySecret = "kDqlGeJTKw6tJtFYiaY8vQTFuVIQDs";
|
||||||
|
private final String deepseekApiKey="sk-7f666f993b144d279ae375a015e4de56";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object videoToCharacters(String fileLink){
|
public Object videoToCharacters(String fileLink){
|
||||||
@@ -104,4 +109,26 @@ public class TikHupServiceImpl implements TikHupService{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object deepseekAnalysis(String promptType,String content){
|
||||||
|
Unirest.setTimeouts(0, 0);
|
||||||
|
try{
|
||||||
|
TikPromptVO tikPromptVO = tikPromptMapper.getTikPromptVO(promptType);
|
||||||
|
HttpResponse<String> response = Unirest.post("https://api.deepseek.com/chat/completions")
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.header("Authorization", "Bearer " + deepseekApiKey)
|
||||||
|
.body("{\n \"messages\": [\n {\n \"content\": \""+tikPromptVO.getPrompt()+"\n\n\n原文如下:\n"+content+"\",\n \"role\": \"system\"\n },\n {\n \"content\": \"Hi\",\n \"role\": \"user\"\n }\n ],\n \"model\": \"deepseek-chat\",\n \"frequency_penalty\": 0,\n \"max_tokens\": 8000,\n \"presence_penalty\": 0,\n \"response_format\": {\n \"type\": \"text\"\n },\n \"stop\": null,\n \"stream\": false,\n \"stream_options\": null,\n \"temperature\": 1,\n \"top_p\": 1,\n \"tools\": null,\n \"tool_choice\": \"none\",\n \"logprobs\": false,\n \"top_logprobs\": null\n}")
|
||||||
|
.asString();
|
||||||
|
if(response.getStatus() == 200){
|
||||||
|
return response.getBody();
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return CommonResult.error(500,"文案改写失败!");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,11 +33,11 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 会员中心。默认注释,保证编译速度 -->
|
<!-- 会员中心。默认注释,保证编译速度 -->
|
||||||
<!-- <dependency>-->
|
<dependency>
|
||||||
<!-- <groupId>cn.iocoder.boot</groupId>-->
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
<!-- <artifactId>yudao-module-member</artifactId>-->
|
<artifactId>yudao-module-member</artifactId>
|
||||||
<!-- <version>${revision}</version>-->
|
<version>${revision}</version>
|
||||||
<!-- </dependency>-->
|
</dependency>
|
||||||
|
|
||||||
<!-- 数据报表。默认注释,保证编译速度 -->
|
<!-- 数据报表。默认注释,保证编译速度 -->
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
|
|||||||
Reference in New Issue
Block a user