模拟辩论后端实现

main
heiferleaf 3 months ago
parent c7319a564d
commit 2bee93f3be

@ -3,6 +3,7 @@ package com.learning.newdemo.controller;
import com.learning.newdemo.common.Result;
import com.learning.newdemo.service.WxArgumentService;
import com.learning.newdemo.service.WxDebateService;
import com.learning.newdemo.service.WxReviewService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -24,6 +25,9 @@ public class WxAIController {
@Autowired
private WxReviewService wxReviewService;
@Autowired
private WxDebateService wxDebateService;
private String topic;
private String stance;
@ -43,7 +47,7 @@ public class WxAIController {
log.info("请求内容: {}", params);
try {
String argument = wxArgumentService.getArgument(topic, stance);
String argument = wxArgumentService.GetArgument(topic, stance);
if (argument == null) {
return Result.error("立论获取失败");
}
@ -67,7 +71,7 @@ public class WxAIController {
content = params.get("content");
try {
String review = wxReviewService.getReview(content);
String review = wxReviewService.GetReview(content);
if (review == null) {
return Result.error("复盘获取失败");
}
@ -83,4 +87,26 @@ public class WxAIController {
return Result.error("复盘获取失败:" + e.getMessage());
}
}
@PostMapping("/debate")
public Result<Map<String, Object>> debate(@RequestBody Map<String, String> params){
log.info("请求内容: {}", params);
String history = params.get("history");
String userMessage = params.get("userMessage");
try {
String debate = wxDebateService.GetDebate(history, userMessage);
if (debate == null) {
return Result.error("辩论获取失败");
}
Map<String, Object> data = new HashMap<>();
data.put("debate", debate);
// 查看data
log.info("辩论获取成功:{}", debate);
return Result.success(data);
}catch (Exception e){
log.error("辩论获取失败", e);
return Result.error("辩论获取失败:" + e.getMessage());
}
}
}

@ -1,9 +1,9 @@
package com.learning.newdemo.service;
/**
*
*/
public interface WxArgumentService {
String getArgument(String topic, String stance);
}
package com.learning.newdemo.service;
/**
*
*/
public interface WxArgumentService {
String GetArgument(String topic, String stance);
}

@ -0,0 +1,5 @@
package com.learning.newdemo.service;
public interface WxDebateService {
String GetDebate(String history, String userMessage);
}

@ -1,5 +1,5 @@
package com.learning.newdemo.service;
public interface WxReviewService {
String getReview(String content);
String GetReview(String content);
}

@ -1,95 +1,95 @@
package com.learning.newdemo.service.impl;
import com.learning.newdemo.service.WxArgumentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
@Slf4j
public class WxArgumentServiceImpl implements WxArgumentService {
private final RestTemplate restTemplate;
@Value("${ai.argument.header.Authorization}") private String authorizationHeader;
@Value("${ai.argument.body.message.role-sys}") private String roleSys;
@Value("${ai.argument.body.message.content-sys}") private String contentSys;
@Value("${ai.argument.body.message.role-user}") private String roleUser;
@Value("${ai.argument.body.model}") private String model;
@Value("${ai.argument.body.frequency_penalty}") private int frequencyPenalty;
@Value("${ai.argument.body.max_tokens}") private int maxTokens;
@Value("${ai.argument.body.presence_penalty}") private int presencePenalty;
@Value("${ai.argument.body.response_format}") private String responseFormatType;
@Value("${ai.argument.body.stream}") private boolean stream;
@Value("${ai.argument.body.temperature}") private double temperature;
@Value("${ai.argument.body.top_p}") private double topP;
@Value("${ai.argument.body.tool_choice}") private String toolChoice;
@Value("${ai.argument.body.logprobs}") private boolean logprobs;
@Value("${ai.argument.url}") private String url;
public WxArgumentServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String getArgument(String topic, String stance) {
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", authorizationHeader);
// 构建请求体,使用字符串拼接
String requestBody = "{"
+ "\"messages\": ["
+ "{"
+ "\"role\": \"" + roleSys + "\","
+ "\"content\": \"" + escapeJson(contentSys) + "\""
+ "},"
+ "{"
+ "\"role\": \"" + roleUser + "\","
+ "\"content\": \"" + escapeJson(topic + ",我的立场是" + stance) + "\""
+ "}"
+ "],"
+ "\"model\": \"" + model + "\","
+ "\"frequency_penalty\": " + frequencyPenalty + ","
+ "\"max_tokens\": " + maxTokens + ","
+ "\"presence_penalty\": " + presencePenalty + ","
+ "\"response_format\": {\"type\": \"" + responseFormatType + "\"},"
+ "\"stop\": null,"
+ "\"stream\": " + stream + ","
+ "\"stream_options\": null,"
+ "\"temperature\": " + temperature + ","
+ "\"top_p\": " + topP + ","
+ "\"tools\": null,"
+ "\"tool_choice\": \"" + toolChoice + "\","
+ "\"logprobs\": " + logprobs + ","
+ "\"top_logprobs\": null"
+ "}";
log.info("请求体:{}", requestBody);
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
return response.getBody();
} catch (Exception e) {
log.error("向AI获取立论失败", e);
return null;
}
}
// 工具方法:转义 JSON 字符串中的特殊字符
private String escapeJson(String input) {
if (input == null) return "";
return input.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
package com.learning.newdemo.service.impl;
import com.learning.newdemo.service.WxArgumentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
@Slf4j
public class WxArgumentServiceImpl implements WxArgumentService {
private final RestTemplate restTemplate;
@Value("${ai.argument.header.Authorization}") private String authorizationHeader;
@Value("${ai.argument.body.message.role-sys}") private String roleSys;
@Value("${ai.argument.body.message.content-sys}") private String contentSys;
@Value("${ai.argument.body.message.role-user}") private String roleUser;
@Value("${ai.argument.body.model}") private String model;
@Value("${ai.argument.body.frequency_penalty}") private int frequencyPenalty;
@Value("${ai.argument.body.max_tokens}") private int maxTokens;
@Value("${ai.argument.body.presence_penalty}") private int presencePenalty;
@Value("${ai.argument.body.response_format}") private String responseFormatType;
@Value("${ai.argument.body.stream}") private boolean stream;
@Value("${ai.argument.body.temperature}") private double temperature;
@Value("${ai.argument.body.top_p}") private double topP;
@Value("${ai.argument.body.tool_choice}") private String toolChoice;
@Value("${ai.argument.body.logprobs}") private boolean logprobs;
@Value("${ai.argument.url}") private String url;
public WxArgumentServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String GetArgument(String topic, String stance) {
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", authorizationHeader);
// 构建请求体,使用字符串拼接
String requestBody = "{"
+ "\"messages\": ["
+ "{"
+ "\"role\": \"" + roleSys + "\","
+ "\"content\": \"" + escapeJson(contentSys) + "\""
+ "},"
+ "{"
+ "\"role\": \"" + roleUser + "\","
+ "\"content\": \"" + escapeJson(topic + ",我的立场是" + stance) + "\""
+ "}"
+ "],"
+ "\"model\": \"" + model + "\","
+ "\"frequency_penalty\": " + frequencyPenalty + ","
+ "\"max_tokens\": " + maxTokens + ","
+ "\"presence_penalty\": " + presencePenalty + ","
+ "\"response_format\": {\"type\": \"" + responseFormatType + "\"},"
+ "\"stop\": null,"
+ "\"stream\": " + stream + ","
+ "\"stream_options\": null,"
+ "\"temperature\": " + temperature + ","
+ "\"top_p\": " + topP + ","
+ "\"tools\": null,"
+ "\"tool_choice\": \"" + toolChoice + "\","
+ "\"logprobs\": " + logprobs + ","
+ "\"top_logprobs\": null"
+ "}";
log.info("请求体:{}", requestBody);
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
return response.getBody();
} catch (Exception e) {
log.error("向AI获取立论失败", e);
return null;
}
}
// 工具方法:转义 JSON 字符串中的特殊字符
private String escapeJson(String input) {
if (input == null) return "";
return input.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}

@ -0,0 +1,93 @@
package com.learning.newdemo.service.impl;
import com.learning.newdemo.service.WxDebateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
@Slf4j
public class WxDebateServiceImpl implements WxDebateService {
// 通过构造函数从IOC容器中注入RestTemplate
private final RestTemplate restTemplate;
@Value("${ai.debate.body.message.content-sys}") private String contentSys;
@Value("${ai.debate.header.Authorization}") private String authorizationHeader;
@Value("${ai.debate.body.message.role-user}") private String roleUser;
@Value("${ai.debate.body.model}") private String model;
@Value("${ai.debate.body.message.role-sys}") private String roleSys;
@Value("${ai.debate.body.frequency_penalty}") private int frequencyPenalty;
@Value("${ai.debate.body.max_tokens}") private int maxTokens;
@Value("${ai.debate.body.presence_penalty}") private int presencePenalty;
@Value("${ai.debate.body.response_format}") private String responseFormatType;
@Value("${ai.debate.body.stream}") private boolean stream;
@Value("${ai.debate.body.temperature}") private double temperature;
@Value("${ai.debate.body.top_p}") private double topP;
@Value("${ai.debate.body.tool_choice}") private String toolChoice;
@Value("${ai.debate.body.logprobs}") private boolean logprobs;
@Value("${ai.debate.url}") private String url;
public WxDebateServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String GetDebate(String history, String userMessage){
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", authorizationHeader);
StringBuilder requestBodyBuilder = new StringBuilder();
requestBodyBuilder.append("{")
.append("\"messages\": [")
.append("{")
.append("\"role\": \"").append(roleSys).append("\",")
.append("\"content\": \"").append(escapeJson(contentSys)).append("\"")
.append("},")
.append("{")
.append("\"role\": \"").append(roleUser).append("\",")
.append("\"content\": \"").append(escapeJson("历史对话记录" + history + ",用户发言为" + userMessage)).append("\"")
.append("}")
.append("],")
.append("\"model\": \"").append(model).append("\",")
.append("\"frequency_penalty\": ").append(frequencyPenalty).append(",")
.append("\"max_tokens\": ").append(maxTokens).append(",")
.append("\"presence_penalty\": ").append(presencePenalty).append(",")
.append("\"response_format\": {\"type\": \"").append(responseFormatType).append("\"},")
.append("\"stop\": null,")
.append("\"stream\": ").append(stream).append(",")
.append("\"stream_options\": null,")
.append("\"temperature\": ").append(temperature).append(",")
.append("\"top_p\": ").append(topP).append(",")
.append("\"tools\": null,")
.append("\"tool_choice\": \"").append(toolChoice).append("\",")
.append("\"logprobs\": ").append(logprobs).append(",")
.append("\"top_logprobs\": null")
.append("}");
String requestBody = requestBodyBuilder.toString();
log.info("请求体:{}", requestBody);
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
return response.getBody();
} catch (Exception e){
log.error("模拟辩论获取失败", e);
return null;
}
}
// 工具方法:转义 JSON 字符串中的特殊字符
private String escapeJson(String input) {
if (input == null) return "";
return input.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
}

@ -34,7 +34,7 @@ public class WxReviewServiceImpl implements WxReviewService {
}
@Override
public String getReview(String content) {
public String GetReview(String content) {
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

@ -1,2 +0,0 @@
# 主要配置在application.yml中
# 此文件用于避免IDE报错

@ -107,6 +107,7 @@ ai:
top_p: 1
tool_choice: "none"
logprobs: false
review:
url: https://api.deepseek.com/chat/completions
header:
@ -227,6 +228,137 @@ ai:
top_p: 1
tool_choice: "none"
logprobs: false
debate:
url: https://api.deepseek.com/chat/completions
headers:
Authorization: "Bearer sk-53428f3b07ff426f8c11d988f649b5e7"
body:
message:
role-sys: system
content-sys: |
竞技辩论指导手册(简洁版)
现在假设你是一个专业的华语辩论辩手,你需要阅读下面的竞技辩论指导手册,学习如何坚守自己的立场,打出一场精彩的比赛。(注意,所有交锋环节,包括质询,接质,自由辩论你一次都只能输出一个问题的内容,模拟场上真实的比赛节奏)
一、基础准备
1. 理解辩题
- 先拆解核心概念(比如"语词平等"要明确指什么)
- 列出正反方可能的论点
- 准备2-3种定义方式预防定义战
2. 证据收集
- 每个论点配1-2个具体案例
- 找近年的学术研究(心理学/社会学优先)
- 准备可比数据(比如"实施前vs实施后"对比)
二、辩论策略
1. 立论结构
1. 定义关键概念
2. 论证必要性(为什么这问题重要)
3. 提出解决机制(具体怎么做)
4. 比较优势(比对方方案好在哪)
5. 价值升华(对社会/个人的意义)
2. 反驳技巧
- 直接反驳:指出对方逻辑漏洞
- 替代解释:提供其他可能性
- 削弱影响:证明对方论点不重要
三、实用话术
1. 定义争夺
"对方对XX的理解过于狭隘实际上应该包含..."
"这个定义在XX学者的研究中明确指..."
2. 数据质疑
"该研究样本量仅200人代表性不足"
"过去五年的新数据显示..."
3. 价值比较
"短期可能有效,但长期会导致..."
"解决了A问题却恶化了B问题"
四、常见错误避免
1. 逻辑问题
- 不偷换概念
- 不循环论证
- 不稻草人谬误(歪曲对方观点)
2. 表达问题
- 避免绝对化表述("绝对""永远"
- 复杂理论简单化解释
- 关键数据要说明来源
五、临场技巧
1. 质询要领
- 问题要封闭(让对方只能答是/否)
- 连续追问不超过3个
- 提前准备"杀手锏问题"
2. 自由辩论
- 30秒内完成一个论点
- 标记战场("关于XX问题我方认为..."
- 不纠缠细节,保持主线
六、经典辩论场景应对
1. 当对方说"现实做不到"
回应方向:
- 已有试点成功案例(举例)
- 技术/制度可行性分析
- 反问"那更好的解决方案是什么"
2. 当对方强调"特殊情况"
回应策略:
- 证明不具代表性
- 展示整体数据
- 指出例外不能否定原则
七、评委说服技巧
1. 专业评委
- 多引用学术研究
- 展示逻辑推导过程
- 使用专业术语
2. 大众评委
- 多讲生活案例
- 用比喻解释复杂概念
- 适当情感共鸣
八、自我检查清单
1. 每个论点是否有证据支持?
2. 反驳是否针对对方核心主张?
3. 价值主张是否清晰有力?
4. 时间分配是否合理?
九、备用锦囊
1. 万能案例库准备5个跨领域案例
2. 名人名言各领域3-5句
3. 紧急话术(当卡壳时:"这个问题需要分三个层面来看..."
十、赛后提升
1. 记录被反驳成功的论点
2. 收集新的证据材料
3. 优化表达方式(哪些话评委反应好)
[使用说明]
1. 比赛前通读"基础准备"和"策略"部分
2. 场上根据情况调用对应话术
3. 赛后完成"自我检查"和"提升"
总字数约3500字可根据需要增减
这份手册的特点:
1. 说人话,不装高深
2. 直接可用,不需要翻译
3. 重点突出实战技巧
4. 兼顾新手和老手需求
使用时只需要告诉我:
- 你的持方(正方/反方)
- 辩题类型(政策/价值/事实)
- 特别需求(如重点攻定义/数据)
role-user: user
model: deepseek-chat
frequency_penalty: 0
max_tokens: 2048
presence_penalty: 0
response_format: text
stream: false
temperature: 1
top_p: 1
tool_choice: "none"
logprobs: false
# JWT配置
jwt:
secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz

Loading…
Cancel
Save