翻译模型

This commit is contained in:
spllzh
2025-10-12 20:46:59 +08:00
parent 5f2c952a6e
commit 71c0a04b53
24 changed files with 532 additions and 303 deletions

View File

@@ -159,5 +159,6 @@ public class PasswordUtil {

View File

@@ -143,5 +143,6 @@ public class ServiceManager {

View File

@@ -120,5 +120,6 @@ public class AliyunConfig {

View File

@@ -0,0 +1,291 @@
package com.rj.controller;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.lang.System;
import java.util.Collections;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.generation.TranslationOptions;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
/**
* 翻译、法律、意图理解控制器
*
* @author 李中华
* @date 2025/1/3
*/
@Slf4j
@RestController
@RequestMapping("/api/translation")
@Tag(name = "文本模型AI服务", description = "翻译、法律咨询、意图理解API接口")
public class TextModelController {
/**
* 翻译请求DTO
*/
@Data
public static class TranslationRequest {
@NotBlank(message = "原语言文字不能为空")
private String sourceText;
@NotBlank(message = "目标语言不能为空")
private String targetLanguage;
@NotBlank(message = "原语言不能为空")
private String sourceLanguage;
@NotBlank(message = "大模型名称")
private String model;
}
/**
* 法律咨询请求DTO
*/
@Data
public static class LegalRequest {
@NotBlank(message = "法律问题不能为空")
private String question;
private String category;
private String jurisdiction;
@NotBlank(message = "大模型名称")
private String model;
}
/**
* 意图理解请求DTO
*/
@Data
public static class IntentRequest {
@NotBlank(message = "输入文本不能为空")
private String text;
private String context;
private String domain;
@NotBlank(message = "大模型名称")
private String model;
}
/**
* 翻译接口
*/
@PostMapping("/translate")
@Operation(summary = "文本翻译", description = "将文本从源语言翻译到目标语言")
public ResponseEntity<Map<String, Object>> translate(
@Parameter(description = "翻译请求参数") @Valid @RequestBody TranslationRequest request) {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始翻译,模型: {}, 目标语言: {}, 文本长度: {}",
request.getModel(), request.getTargetLanguage(), request.getSourceText().length());
// 模拟翻译处理(实际项目中应该调用翻译服务)
String translatedText = performTranslation(
request.getSourceText(),
request.getModel(),
request.getTargetLanguage()
);
result.put("success", true);
result.put("message", "翻译成功");
result.put("sourceText", request.getSourceText());
result.put("translatedText", translatedText);
result.put("sourceLanguage", request.getSourceLanguage());
result.put("targetLanguage", request.getTargetLanguage());
result.put("translationConfidence", 0.95);
result.put("processingTimeMs", 1200);
result.put("requestId", generateRequestId());
result.put("timestamp", LocalDateTime.now());
log.info("翻译完成,目标文本长度: {}", translatedText.length());
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("翻译失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("message", "翻译失败: " + e.getMessage());
result.put("error", e.getClass().getSimpleName());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 法律咨询接口
*/
@PostMapping("/legal")
@Operation(summary = "法律咨询", description = "提供法律问题咨询和建议")
public ResponseEntity<Map<String, Object>> legalConsultation(
@Parameter(description = "法律咨询请求参数") @Valid @RequestBody LegalRequest request) {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始法律咨询,问题类别: {}, 管辖区域: {}, 问题长度: {}",
request.getCategory(), request.getJurisdiction(), request.getQuestion().length());
// 模拟法律咨询处理实际项目中应该调用AI法律服务
Map<String, Object> legalResponse = performLegalConsultation(request);
result.put("success", true);
result.put("message", "法律咨询完成");
result.put("question", request.getQuestion());
result.put("answer", legalResponse.get("answer"));
result.put("category", legalResponse.get("category"));
result.put("jurisdiction", legalResponse.get("jurisdiction"));
result.put("confidence", legalResponse.get("confidence"));
result.put("relatedLaws", legalResponse.get("relatedLaws"));
result.put("suggestions", legalResponse.get("suggestions"));
result.put("processingTimeMs", 2500);
result.put("requestId", generateRequestId());
result.put("timestamp", LocalDateTime.now());
log.info("法律咨询完成,回答长度: {}", legalResponse.get("answer").toString().length());
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("法律咨询失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("message", "法律咨询失败: " + e.getMessage());
result.put("error", e.getClass().getSimpleName());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 意图理解接口
*/
@PostMapping("/intent")
@Operation(summary = "意图理解", description = "分析文本的意图和情感")
public ResponseEntity<Map<String, Object>> intentAnalysis(
@Parameter(description = "意图理解请求参数") @Valid @RequestBody IntentRequest request) {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始意图分析,领域: {}, 上下文: {}, 文本长度: {}",
request.getDomain(), request.getContext(), request.getText().length());
// 模拟意图理解处理实际项目中应该调用NLP服务
Map<String, Object> intentResponse = performIntentAnalysis(request);
result.put("success", true);
result.put("message", "意图分析完成");
result.put("text", request.getText());
result.put("intent", intentResponse.get("intent"));
result.put("confidence", intentResponse.get("confidence"));
result.put("entities", intentResponse.get("entities"));
result.put("sentiment", intentResponse.get("sentiment"));
result.put("emotion", intentResponse.get("emotion"));
result.put("domain", intentResponse.get("domain"));
result.put("processingTimeMs", 800);
result.put("requestId", generateRequestId());
result.put("timestamp", LocalDateTime.now());
log.info("意图分析完成,识别意图: {}", intentResponse.get("intent"));
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("意图分析失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("message", "意图分析失败: " + e.getMessage());
result.put("error", e.getClass().getSimpleName());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 执行翻译的模拟方法
*/
private String performTranslation(String sourceText, String model, String targetLanguage) {
Generation gen = new Generation();
Message userMsg = Message.builder()
.role(Role.USER.getValue())
.content(sourceText)
.build();
TranslationOptions options = TranslationOptions.builder()
.sourceLang("auto")
// .targetLang("English")
.targetLang(targetLanguage)
.build();
GenerationParam param = GenerationParam.builder()
// 若没有配置环境变量请用阿里云百炼API Key将下行替换为.apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
// .model("qwen-mt-plus")
.model(model)
.messages(Collections.singletonList(userMsg))
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
.translationOptions(options)
.build();
try {
GenerationResult call = gen.call(param);
String content = call.getOutput().getChoices().get(0).getMessage().getContent();
log.info("翻译完成,结果长度: {} ,内容是:{} ", content.length(),content);
return content;
} catch (NoApiKeyException e) {
throw new RuntimeException(e);
} catch (InputRequiredException e) {
throw new RuntimeException(e);
}
}
/**
* 执行法律咨询的模拟方法
*/
private Map<String, Object> performLegalConsultation(LegalRequest request) {
Map<String, Object> response = new HashMap<>();
response.put("answer", "根据您的问题,我建议您咨询专业律师。这是一个复杂的法律问题,需要详细分析具体情况。");
response.put("category", request.getCategory() != null ? request.getCategory() : "一般法律咨询");
response.put("jurisdiction", request.getJurisdiction() != null ? request.getJurisdiction() : "中国大陆");
response.put("confidence", 0.85);
response.put("relatedLaws", new String[]{"民法典", "合同法", "劳动法"});
response.put("suggestions", new String[]{"收集相关证据", "咨询专业律师", "了解相关法律条文"});
return response;
}
/**
* 执行意图分析的模拟方法
*/
private Map<String, Object> performIntentAnalysis(IntentRequest request) {
Map<String, Object> response = new HashMap<>();
response.put("intent", "查询信息");
response.put("confidence", 0.92);
response.put("entities", new String[]{"时间", "地点", "人物"});
response.put("sentiment", "中性");
response.put("emotion", "平静");
response.put("domain", request.getDomain() != null ? request.getDomain() : "通用");
return response;
}
/**
* 生成请求ID
*/
private String generateRequestId() {
return "REQ_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000);
}
}

View File

@@ -1,5 +1,12 @@
package com.rj.controller;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rj.entity.VideoImageAnalysis;
@@ -607,7 +614,13 @@ public class VideoImageAnalysisController {
analysis.setUpdatedAt(now);
// 调用阿里云AI服务进行实际分析
Map<String, Object> aiResult = performAiAnalysisWithDetails(model, type, userQuestion, analysis.getVideoImageTempUrl());
Map<String, Object> aiResult=null;
if ("video".equals(type) ){
aiResult = performAiAnalysisWithDetailsForVideo(model, type, userQuestion, analysis.getVideoImageTempUrl());
}else {
aiResult = performAiAnalysisWithDetails(model, type, userQuestion, analysis.getVideoImageTempUrl());
}
String aiResponse = (String) aiResult.get("content");
analysis.setResponseContent(aiResponse);
@@ -619,10 +632,15 @@ public class VideoImageAnalysisController {
// 记录AI分析结果和token使用情况
analysis.setFinishReason("stop");
analysis.setUsagePromptTokens((Integer) aiResult.getOrDefault("promptTokens", 0));
analysis.setUsageCompletionTokens((Integer) aiResult.getOrDefault("completionTokens", 0));
analysis.setUsageTotalTokens((Integer) aiResult.getOrDefault("totalTokens", 0));
try {
analysis.setUsagePromptTokens((Integer) aiResult.getOrDefault("promptTokens", Integer.valueOf(0)));
analysis.setUsageCompletionTokens((Integer) aiResult.getOrDefault("completionTokens", Integer.valueOf(0)));
analysis.setUsageTotalTokens((Integer) aiResult.getOrDefault("totalTokens", Integer.valueOf(0)));
} catch (Exception e) {
log.error("获取token使用情况失败:{}" ,e );
}
// 保存分析记录
boolean success = videoImageAnalysisService.saveVideoImageAnalysis(analysis);
@@ -706,7 +724,46 @@ public class VideoImageAnalysisController {
throw new RuntimeException("提取对象名失败: " + e.getMessage());
}
}
private Map<String, Object> performAiAnalysisWithDetailsForVideo(String model, String type, String userQuestion, String fileUrl) {
MultiModalConversation conv = new MultiModalConversation();
Map<String, Object> result = new HashMap<>();
// fps 可参数控制视频抽帧频率,表示每隔 1/fps 秒抽取一帧完整用法请参见https://help.aliyun.com/zh/model-studio/use-qwen-by-calling-api?#2ed5ee7377fum
Map<String, Object> params = new HashMap<>();
// params.put("video", "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241115/cqqkru/1.mp4");
params.put("video",fileUrl);
params.put("fps", 2);
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(
params,
Collections.singletonMap("text", userQuestion))).build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model)
.messages(Arrays.asList(userMessage))
.build();
result.put("requestData", userMessage.toString());
MultiModalConversationResult callResult = null;
try {
callResult = conv.call(param);
} catch (NoApiKeyException e) {
throw new RuntimeException(e);
} catch (UploadFileException e) {
throw new RuntimeException(e);
}
result.put("responseData", callResult.toString());
System.out.println(callResult.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text"));
result.put("content",callResult.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text") );
result.put("promptTokens",callResult.getUsage().getInputTokens() );
result.put("completionTokens",callResult.getUsage().getOutputTokensDetails() );
result.put("totalTokens",callResult.getUsage().getTotalTokens() );
return result;
}
/**
* 执行AI分析 - 调用阿里云通义千问API返回详细信息
*/
@@ -737,27 +794,19 @@ public class VideoImageAnalysisController {
imageContent.put("type", type);
if (type.equals("video")) {
/**
* [{
* "role": "user",
* "content": [
* {
* "type": "video",
* "video": [
* "https://img.alicdn.com/imgextra/i3/O1CN01K3SgGo1eqmlUgeE9b_!!6000000003923-0-tps-3840-2160.jpg",
* "https://img.alicdn.com/imgextra/i4/O1CN01BjZvwg1Y23CF5qIRB_!!6000000003000-0-tps-3840-2160.jpg",
* "https://img.alicdn.com/imgextra/i4/O1CN01Ib0clU27vTgBdbVLQ_!!6000000007859-0-tps-3840-2160.jpg",
* "https://img.alicdn.com/imgextra/i1/O1CN01aygPLW1s3EXCdSN4X_!!6000000005710-0-tps-3840-2160.jpg"]
* },
* {
* "type": "text",
* "text": "描述这个视频的具体过程"
* }]}]
*/
// 检查是否提供了图片序列
if (fileUrl == null || fileUrl.trim().isEmpty()) {
throw new RuntimeException("视频分析需要提供图片序列,当前未提供任何文件");
}
// 检查是否为图片序列通过URL数量判断
// 这里假设如果fileUrl包含多个URL用逗号分隔则为图片序列
// 满足要求的图片序列
Map<String, Object> videoContent = new HashMap<>();
videoContent.put("video", Arrays.asList(fileUrl));
content.add(videoContent);
imageContent.put("video", Arrays.asList(fileUrl));
content.add(imageContent);
}else if (type.equals("image_url")) {
} else if (type.equals("image_url")) {
/**
* [{"role": "user","content": [
* {"type": "image_url",
@@ -789,11 +838,12 @@ public class VideoImageAnalysisController {
// 创建HTTP实体
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
// 保存请求数据到结果中
String requestDataJson = objectMapper.writeValueAsString(requestBody);
log.info("调用阿里云AI分析APIURL{}, 请求体:{}", apiUrl, requestDataJson);
log.info("调用阿里云AI分析API 请求体:{}", requestDataJson);
Map<String, Object> result = new HashMap<>();
result.put("requestData", requestDataJson);
// 发送请求
ResponseEntity<String> response = restTemplate.exchange(
apiUrl,
@@ -801,13 +851,12 @@ public class VideoImageAnalysisController {
entity,
String.class
);
log.info("阿里云AI分析API响应状态{}", response.getStatusCode());
log.info("阿里云AI分析API响应内容{}", response.getBody());
// 保存响应数据
String responseDataJson = response.getBody();
result.put("responseData", responseDataJson);
if (response.getStatusCode().is2xxSuccessful()) {
// 解析响应
JsonNode responseJson = objectMapper.readTree(response.getBody());
@@ -819,7 +868,7 @@ public class VideoImageAnalysisController {
// 记录token使用情况
JsonNode usage = responseJson.path("usage");
Map<String, Object> result = new HashMap<>();
result.put("content", contentText);
if (!usage.isMissingNode()) {
@@ -839,9 +888,7 @@ public class VideoImageAnalysisController {
result.put("totalTokens", 0);
}
// 添加请求和响应数据
result.put("requestData", requestDataJson);
result.put("responseData", responseDataJson);
return result;
} else {

View File

@@ -381,5 +381,6 @@ public class MenuController {

View File

@@ -351,5 +351,6 @@ public class RoleController {

View File

@@ -357,5 +357,6 @@ public class UserRoleController {

View File

@@ -123,5 +123,6 @@ public class DifyWorkflowResponseDto {

View File

@@ -66,5 +66,6 @@ public interface CustomerProfileAnalysisMapper extends BaseMapper<CustomerProfil

View File

@@ -87,5 +87,6 @@ public interface ICustomerProfileAnalysisService extends IService<CustomerProfil

View File

@@ -122,5 +122,6 @@ public class CustomerProfileAnalysisServiceImpl extends ServiceImpl<CustomerProf

View File

@@ -94,5 +94,6 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IM

View File

@@ -94,5 +94,6 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR

View File

@@ -94,5 +94,6 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i

View File

@@ -81,6 +81,18 @@ spring:

View File

@@ -262,6 +262,18 @@

View File

@@ -1,32 +0,0 @@
-- 为 audio_management 表添加销售人员电话字段
-- 执行日期: 2025-01-27
-- 添加销售人员电话字段
ALTER TABLE `audio_management`
ADD COLUMN `sales_phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '销售人员电话'
AFTER `sales_name`;

View File

@@ -1,21 +0,0 @@
-- 为 tts_request_log 表添加音频名称字段
ALTER TABLE `tts_request_log`
ADD COLUMN `audio_name` varchar(255) DEFAULT NULL COMMENT '音频文件名' AFTER `minio_url`;
-- 添加索引以提高查询性能
ALTER TABLE `tts_request_log`
ADD INDEX `idx_audio_name` (`audio_name`);

View File

@@ -1,22 +0,0 @@
-- 为 topsales_score_result 表添加销售人员和经销商信息字段
-- 执行日期: 2025-01-27
-- 添加销售人员姓名字段
ALTER TABLE `topsales_score_result`
ADD COLUMN `salesperson_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '销售人员姓名'
AFTER `negotiation_deal_score`;
-- 添加销售人员电话字段
ALTER TABLE `topsales_score_result`
ADD COLUMN `salesperson_phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '销售人员电话'
AFTER `salesperson_name`;
-- 添加经销商名称字段
ALTER TABLE `topsales_score_result`
ADD COLUMN `dealer_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '经销商名称'
AFTER `salesperson_phone`;
-- 添加经销商电话字段
ALTER TABLE `topsales_score_result`
ADD COLUMN `dealer_phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '经销商电话'
AFTER `dealer_name`;

View File

@@ -1,192 +0,0 @@
# Customer Profile Analysis 表字段分类
## 1. 主键和基础标识字段 (Primary Key & Basic Identity Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `id` | VARCHAR(36) | NOT NULL | 主键UUID |
| `profile_analysis_record_id` | VARCHAR(255) | NOT NULL | AI分析记录ID |
| `analysis_scene_type` | TINYINT UNSIGNED | NOT NULL | 分析类型1-企微会话 2-AI通话录音 3-AI铭牌(客流) 4-AI铭牌(试驾) |
| `related_business_id` | VARCHAR(255) | NOT NULL | 业务ID根据分析不同传不同的值 1-unionId 2-通话ID 3-客流ID 4-试驾ID |
## 2. 时间相关字段 (Time Related Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `interaction_date` | DATETIME | NOT NULL | 沟通时间AI通话录音-通话开始时间 企微会话-语料消息截至时间 面谈-语料消息截至时间 |
| `created_at` | DATETIME | NOT NULL | 创建时间 |
| `updated_at` | DATETIME | NOT NULL | 更新时间 |
## 3. 经销商和组织信息字段 (Dealer & Organization Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `dealer_code` | VARCHAR(36) | NULL | 经销商编码 |
| `dealer_name` | VARCHAR(100) | NULL | 经销商门店名称 |
| `big_area` | VARCHAR(50) | NULL | 大区 |
| `project_id` | VARCHAR(36) | NULL | 项目ID |
| `project_name` | VARCHAR(100) | NULL | 项目名称 |
## 4. 销售团队信息字段 (Sales Team Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `sales_person_id` | VARCHAR(36) | NULL | 销售顾问ID |
| `sales_person_name` | VARCHAR(50) | NULL | 销售顾问姓名 |
## 5. 商机和客户信息字段 (Opportunity & Customer Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `opportunity_id` | VARCHAR(36) | NULL | 商机ID |
| `client_id` | VARCHAR(36) | NULL | 客户ID |
| `client_name` | VARCHAR(100) | NULL | 客户姓名 |
| `client_phone` | VARCHAR(20) | NULL | 客户电话 |
## 6. 购车意向信息字段 (Purchase Intention Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `purchase_date` | VARCHAR(50) | NULL | 预购日期(示例值:天数) |
| `purchase_type` | VARCHAR(20) | NULL | 购买类型(示例值:新购/置换/增购) |
| `payment_way` | VARCHAR(20) | NULL | 付款方式(示例值:贷款/全款/分期) |
| `competitor_brand` | VARCHAR(50) | NULL | 竞品品牌(示例值:奔驰/宝马/奥迪) |
| `vehicle_usage` | VARCHAR(20) | NULL | 购车用途(示例值:家用/商用/代步) |
| `primary_driver` | VARCHAR(20) | NULL | 实际驾驶人(示例值:本人/家人/其他) |
| `budget_range` | VARCHAR(50) | NULL | 购车预算(示例值:具体预算范围) |
| `purchase_qualification` | VARCHAR(10) | NULL | 购车资质(示例值:是否) |
## 7. 客户个人背景信息字段 (Customer Background Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `education_level` | VARCHAR(20) | NULL | 教育水平(示例值:本科/硕士/高中) |
| `family_composition` | VARCHAR(50) | NULL | 家庭结构(示例值:已婚有子女/单身) |
| `monthly_income` | VARCHAR(50) | NULL | 家庭月收入(示例值:具体收入区间) |
| `job_title` | VARCHAR(50) | NULL | 职业(示例值:教师/工程师/医生) |
| `company_type` | VARCHAR(50) | NULL | 企业性质(示例值:民营企业/国企/外企) |
| `industry_sector` | VARCHAR(50) | NULL | 所属行业(示例值:教育/互联网/金融) |
| `home_address` | VARCHAR(200) | NULL | 详细地址(非枚举,示例值) |
| `family_size` | VARCHAR(10) | NULL | 家庭人数(非枚举,示例值) |
| `hobby` | VARCHAR(200) | NULL | 个人爱好(非枚举,示例值) |
## 8. 客户关注点和偏好字段 (Customer Focus & Preference Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `interest_focus` | VARCHAR(200) | NULL | 兴趣点(示例值:智能驾驶/油耗/空间) |
| `concern_point` | VARCHAR(200) | NULL | 顾虑点(示例值:保养成本/保值率) |
| `current_brand` | VARCHAR(50) | NULL | 保有品牌(非枚举,示例值) |
## 9. 备注和扩展信息字段 (Notes & Extended Information Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `notes` | VARCHAR(500) | NULL | 备注(非枚举,保留名称) |
## 10. 实体情感分析字段 (Entity Sentiment Analysis Fields)
### 10.1 品牌和设计相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_brand` | VARCHAR(10) | NULL | 品牌情感倾向:积极/中性/消极 |
| `entity_brand_reason` | VARCHAR(500) | NULL | 品牌情感倾向原因 |
| `entity_design` | VARCHAR(10) | NULL | 外观设计情感倾向:积极/中性/消极 |
| `entity_design_reason` | VARCHAR(500) | NULL | 外观设计情感倾向原因 |
| `entity_color` | VARCHAR(10) | NULL | 颜色情感倾向:积极/中性/消极 |
| `entity_color_reason` | VARCHAR(500) | NULL | 颜色情感倾向原因 |
### 10.2 车辆尺寸和空间相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_size` | VARCHAR(10) | NULL | 尺寸情感倾向:积极/中性/消极 |
| `entity_size_reason` | VARCHAR(500) | NULL | 尺寸情感倾向原因 |
| `entity_space` | VARCHAR(10) | NULL | 空间情感倾向:积极/中性/消极 |
| `entity_space_reason` | VARCHAR(500) | NULL | 空间情感倾向原因 |
### 10.3 内饰和配置相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_interior` | VARCHAR(10) | NULL | 内饰情感倾向:积极/中性/消极 |
| `entity_interior_reason` | VARCHAR(500) | NULL | 内饰情感倾向原因 |
| `entity_audio` | VARCHAR(10) | NULL | 音响情感倾向:积极/中性/消极 |
| `entity_audio_reason` | VARCHAR(500) | NULL | 音响情感倾向原因 |
| `entity_ivinfo` | VARCHAR(10) | NULL | 车机情感倾向:积极/中性/消极 |
| `entity_ivinfo_reason` | VARCHAR(500) | NULL | 车机情感倾向原因 |
### 10.4 智能驾驶和续航相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_fsd` | VARCHAR(10) | NULL | 智驾情感倾向:积极/中性/消极 |
| `entity_fsd_reason` | VARCHAR(500) | NULL | 智驾情感倾向原因 |
| `entity_mileage` | VARCHAR(10) | NULL | 续航情感倾向:积极/中性/消极 |
| `entity_mileage_reason` | VARCHAR(500) | NULL | 续航情感倾向原因 |
### 10.5 安全和环保相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_safety` | VARCHAR(10) | NULL | 安全情感倾向:积极/中性/消极 |
| `entity_safety_reason` | VARCHAR(500) | NULL | 安全情感倾向原因 |
| `entity_eco` | VARCHAR(10) | NULL | 环保情感倾向:积极/中性/消极 |
| `entity_eco_reason` | VARCHAR(500) | NULL | 环保情感倾向原因 |
| `entity_liscense` | VARCHAR(10) | NULL | 绿牌/路权情感倾向:积极/中性/消极 |
| `entity_liscense_reason` | VARCHAR(500) | NULL | 绿牌/路权情感倾向原因 |
### 10.6 价格和成本相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_price` | VARCHAR(10) | NULL | 价格情感倾向:积极/中性/消极 |
| `entity_price_reason` | VARCHAR(500) | NULL | 价格情感倾向原因 |
| `entity_benefit` | VARCHAR(10) | NULL | 购车权益情感倾向:积极/中性/消极 |
| `entity_benefit_reason` | VARCHAR(500) | NULL | 购车权益情感倾向原因 |
| `entity_cost` | VARCHAR(10) | NULL | 用车成本情感倾向:积极/中性/消极 |
| `entity_cost_reason` | VARCHAR(500) | NULL | 用车成本情感倾向原因 |
| `entity_value` | VARCHAR(10) | NULL | 性价比情感倾向:积极/中性/消极 |
| `entity_value_reason` | VARCHAR(500) | NULL | 性价比情感倾向原因 |
### 10.7 动力和操控相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_power` | VARCHAR(10) | NULL | 动力情感倾向:积极/中性/消极 |
| `entity_power_reason` | VARCHAR(500) | NULL | 动力情感倾向原因 |
| `entity_control` | VARCHAR(10) | NULL | 操控情感倾向:积极/中性/消极 |
| `entity_control_reason` | VARCHAR(500) | NULL | 操控情感倾向原因 |
### 10.8 服务和政策相关情感
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `entity_tradein` | VARCHAR(10) | NULL | 置换政策情感倾向:积极/中性/消极 |
| `entity_tradein_reason` | VARCHAR(500) | NULL | 置换政策情感倾向原因 |
| `entity_finance` | VARCHAR(10) | NULL | 金融方案情感倾向:积极/中性/消极 |
| `entity_finance_reason` | VARCHAR(500) | NULL | 金融方案情感倾向原因 |
| `entity_warranty` | VARCHAR(10) | NULL | 质保情感倾向:积极/中性/消极 |
| `entity_warranty_reason` | VARCHAR(500) | NULL | 质保情感倾向原因 |
| `entity_delivery` | VARCHAR(10) | NULL | 交付时间情感倾向:积极/中性/消极 |
| `entity_delivery_reason` | VARCHAR(500) | NULL | 交付时间情感倾向原因 |
## 11. 系统管理字段 (System Management Fields)
| 字段名 | 类型 | 是否必填 | 说明 |
|--------|------|----------|------|
| `created_by` | VARCHAR(36) | NULL | 创建人id |
| `updated_by` | VARCHAR(36) | NULL | 更新人id |
| `create_sqlby` | VARCHAR(8) | NULL | 创建sql人 |
| `update_sqlby` | VARCHAR(8) | NULL | 更新人sql人 |
| `record_version` | TINYINT UNSIGNED | DEFAULT 0 | 版本号(乐观锁) |
| `is_deleted` | TINYINT UNSIGNED | NOT NULL DEFAULT 0 | 是否删除 |
## 字段分类总结
### 按功能分类:
1. **基础标识字段** (4个)主键、分析记录ID、分析类型、业务ID
2. **时间字段** (3个):交互时间、创建时间、更新时间
3. **组织架构字段** (5个):经销商、大区、项目信息
4. **人员信息字段** (2个):销售顾问信息
5. **客户信息字段** (4个):商机、客户基本信息
6. **购车意向字段** (8个):购车相关的意向和偏好
7. **客户背景字段** (8个):个人背景和社会属性
8. **关注偏好字段** (3个):兴趣点和顾虑点
9. **备注字段** (1个):扩展备注信息
10. **情感分析字段** (46个):各种实体的情感倾向和原因
11. **系统管理字段** (6个):审计和版本控制
### 按数据来源分类:
- **系统生成字段**id、created_at、updated_at、record_version、is_deleted
- **业务输入字段**:大部分业务相关字段
- **AI分析字段**所有entity_*字段
- **用户输入字段**:客户基本信息、购车意向等
### 按更新频率分类:
- **静态字段**:客户背景信息、组织架构信息
- **动态字段**:情感分析结果、购车意向
- **系统字段**:时间戳、版本号等

View File

@@ -0,0 +1,97 @@
package com.rj.ai;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import java.lang.System;
import java.util.Collections;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.generation.TranslationOptions;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
public class VideoImageToText {
// 若使用新加坡地域的模型,请取消下列注释
// static {Constants.baseHttpApiUrl="https://dashscope-intl.aliyuncs.com/api/v1";}
public static void simpleMultiModalConversationCall()
throws ApiException, NoApiKeyException, UploadFileException {
MultiModalConversation conv = new MultiModalConversation();
// fps 可参数控制视频抽帧频率,表示每隔 1/fps 秒抽取一帧完整用法请参见https://help.aliyun.com/zh/model-studio/use-qwen-by-calling-api?#2ed5ee7377fum
Map<String, Object> params = new HashMap<>();
// params.put("video", "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241115/cqqkru/1.mp4");
params.put("video",
"http://101.35.52.237:19005/car/20251012_094805_c50e423f61a5429ba2984500e43acc1f.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20251012%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251012T014810Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=eaa996f9992c2e48acf22f3148328265a9b98630be5bb9dcbe85404a35f923da");
params.put("fps", 2);
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(
params,
Collections.singletonMap("text", "这段视频的内容是什么?"))).build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
// 若没有配置环境变量请用百炼API Key将下行替换为.apiKey("sk-xxx")
// 新加坡和北京地域的API Key不同。获取API Keyhttps://help.aliyun.com/zh/model-studio/get-api-key
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("qwen3-vl-plus")
.messages(Arrays.asList(userMessage))
.build();
MultiModalConversationResult result = conv.call(param);
System.out.println(result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text"));
Map<String, Object> resultoo = new HashMap<>();
resultoo.put("promptTokens",result.getUsage().getInputTokens() );
resultoo.put("completionTokens",result.getUsage().getOutputTokensDetails() );
resultoo.put("totalTokens",result.getUsage().getTotalTokens() );
}
public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
Generation gen = new Generation();
Message userMsg = Message.builder()
.role(Role.USER.getValue())
.content("我看到这个视频后没有笑")
.build();
TranslationOptions options = TranslationOptions.builder()
.sourceLang("auto")
.targetLang("English")
.build();
GenerationParam param = GenerationParam.builder()
// 若没有配置环境变量请用阿里云百炼API Key将下行替换为.apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("qwen-mt-plus")
.messages(Collections.singletonList(userMsg))
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
.translationOptions(options)
.build();
return gen.call(param);
}
public static void main(String[] args) {
try {
// simpleMultiModalConversationCall();
GenerationResult generationResult = callWithMessage();
System.out.println(generationResult.getOutput());
System.out.println(generationResult.getUsage());
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.exit(0);
}
}

View File

@@ -145,6 +145,18 @@ public class TtsRequestLogShortUrlTest {