diff --git a/Debate_backend/.idea/uiDesigner.xml b/Debate_backend/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/Debate_backend/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Debate_backend/.idea/vcs.xml b/Debate_backend/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/Debate_backend/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Debate_backend/src/main/java/com/learning/newdemo/common/Result.java b/Debate_backend/src/main/java/com/learning/newdemo/common/Result.java index 38fcf5f..1c18e82 100644 --- a/Debate_backend/src/main/java/com/learning/newdemo/common/Result.java +++ b/Debate_backend/src/main/java/com/learning/newdemo/common/Result.java @@ -8,6 +8,7 @@ import java.io.Serializable; * 统一API返回结果封装 */ @Data +// Serializable接口的作用是:标记当前类可以通过序列化在网络中传播 public class Result implements Serializable { private static final long serialVersionUID = 1L; diff --git a/Debate_backend/src/main/java/com/learning/newdemo/controller/WxAIController.java b/Debate_backend/src/main/java/com/learning/newdemo/controller/WxAIController.java new file mode 100644 index 0000000..671b534 --- /dev/null +++ b/Debate_backend/src/main/java/com/learning/newdemo/controller/WxAIController.java @@ -0,0 +1,50 @@ +package com.learning.newdemo.controller; + + +import com.learning.newdemo.common.Result; +import com.learning.newdemo.service.WxArgumentService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@RestController +@RequestMapping("api/ai") +public class WxAIController { + @Autowired + private WxArgumentService wxArgumentService; + + private String topic; + + private String stance; + + @PostMapping("/argument") + public Result> getArgument(@RequestBody Map params){ + topic = params.get("topic"); + stance = params.get("stance"); + + if(topic == null || stance == null){ + return Result.error("立论主题或者内容为空"); + } + + try { + String argument = wxArgumentService.getArgument(topic, stance); + if (argument == null) { + return Result.error("立论获取失败"); + } + + Map data = new HashMap<>(); + data.put("argument", argument); + return Result.success(data); + }catch (Exception e){ + log.error("立论获取失败", e); + return Result.error("立论获取失败:" + e.getMessage()); + } + } +} diff --git a/Debate_backend/src/main/java/com/learning/newdemo/service/WxArgumentService.java b/Debate_backend/src/main/java/com/learning/newdemo/service/WxArgumentService.java new file mode 100644 index 0000000..7477f7a --- /dev/null +++ b/Debate_backend/src/main/java/com/learning/newdemo/service/WxArgumentService.java @@ -0,0 +1,9 @@ +package com.learning.newdemo.service; + +/** + * 微信立论助手接口 + */ + +public interface WxArgumentService { + String getArgument(String topic, String stance); +} diff --git a/Debate_backend/src/main/java/com/learning/newdemo/service/impl/WxArgumentServiceImpl.java b/Debate_backend/src/main/java/com/learning/newdemo/service/impl/WxArgumentServiceImpl.java new file mode 100644 index 0000000..2050b1c --- /dev/null +++ b/Debate_backend/src/main/java/com/learning/newdemo/service/impl/WxArgumentServiceImpl.java @@ -0,0 +1,150 @@ +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.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +@Slf4j +public class WxArgumentServiceImpl implements WxArgumentService { + + // 依赖注入 + private final RestTemplate restTemplate; + + // 使用@Value注解注入配置属性 + @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.stop}") + private String stop; + + @Value("${ai.argument.body.stream}") + private boolean stream; + + @Value("${ai.argument.body.stream_options}") + private String streamOptions; + + @Value("${ai.argument.body.temperature}") + private double temperature; + + @Value("${ai.argument.body.top_p}") + private double topP; + + @Value("${ai.argument.body.tools}") + private String tools; + + @Value("${ai.argument.body.tool_choice}") + private String toolChoice; + + @Value("${ai.argument.body.logprobs}") + private boolean logprobs; + + @Value("${ai.argument.body.top_logprobs}") + private String topLogprobs; + + @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 = String.format( + "{" + + "\"messages\": [" + + "{" + + "\"role\": \"%s\"," + + "\"content\": \"%s\"" + + "}," + + "{" + + "\"role\": \"%s\"," + + "\"content\": \"%s\\n我的立场是%s\"" + + "}" + + "]," + + "\"model\": \"%s\"," + + "\"frequency_penalty\": %d," + + "\"max_tokens\": %d," + + "\"presence_penalty\": %d," + + "\"response_format\": {" + + "\"type\": \"%s\"" + + "}," + + "\"stop\": %s," + + "\"stream\": %b," + + "\"stream_options\": %s," + + "\"temperature\": %f," + + "\"top_p\": %f," + + "\"tools\": %s," + + "\"tool_choice\": \"%s\"," + + "\"logprobs\": %b," + + "\"top_logprobs\": %s" + + "}", + roleSys, + contentSys, + roleUser, + topic, + stance, + model, + frequencyPenalty, + maxTokens, + presencePenalty, + responseFormatType, + stop, + stream, + streamOptions, + temperature, + topP, + tools, + toolChoice, + logprobs, + topLogprobs + ); + + log.info("请求体:{}", requestBody); + + HttpEntity requestEntity = new HttpEntity<>(requestBody, headers); + + ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); + + return response.getBody(); + }catch(Exception e){ + log.error("向AI获取立论失败",e); + return null; + } + } +} diff --git a/Debate_backend/src/main/java/com/learning/newdemo/service/impl/WxUserServiceImpl.java b/Debate_backend/src/main/java/com/learning/newdemo/service/impl/WxUserServiceImpl.java index 492f7fa..3b080ce 100644 --- a/Debate_backend/src/main/java/com/learning/newdemo/service/impl/WxUserServiceImpl.java +++ b/Debate_backend/src/main/java/com/learning/newdemo/service/impl/WxUserServiceImpl.java @@ -43,7 +43,12 @@ public class WxUserServiceImpl implements WxUserService { + "&js_code=" + code + "&grant_type=authorization_code"; + log.info("请求微信接口URL: {}", url); + ResponseEntity response = restTemplate.getForEntity(url, String.class); + String responseBody = response.getBody(); + + log.info("微信接口返回: {}", responseBody); JSONObject json = JSONObject.parseObject(response.getBody()); // 获取openid diff --git a/Debate_backend/src/main/resources/application.yml b/Debate_backend/src/main/resources/application.yml index f544772..6a5234f 100644 --- a/Debate_backend/src/main/resources/application.yml +++ b/Debate_backend/src/main/resources/application.yml @@ -19,6 +19,101 @@ wechat: appid: wxf1f6d7657e01d48a secret: fc356336a118366f27c384079688bc15 +# AI接口配置 +# AI接口配置 +ai: + argument: + url: https://api.deepseek.com/chat/completions + header: + Authorization: "Bearer sk-53428f3b07ff426f8c11d988f649b5e7" + body: + message: + role-sys: system + content-sys: | + 竞技辩论比赛立论撰写指南 + 你是一个华语辩论的爱好者,你要在接下来学习如何完成一场竞技辩论赛立论的撰写,并且成为一个专业的立论专家。当我给你输入任何一道辩题和持方时,你都能模仿我给你提供的数据,写出一篇完整的,自然段语言式的,辩论圈认可的立论。 + 一、立论稿的本质与功能 + 立论稿是辩论中系统阐述己方观点的开篇陈述,需具备: + 1. 明确的定义判准 + 2. 完整的论证体系 + 3. 严谨的逻辑结构 + 4. 充分的论据支撑 + + 二、标准结构(四段式黄金框架) + 1. 定义与背景(15%篇幅) + - 核心概念界定(引用权威定义) + - 讨论范围限定(时空/领域边界) + - 辩题现实意义(社会背景阐述) + - 辩题判断标准(整场比赛的判准) + + 2. 论证主体(80%篇幅,一般为两个论点) + 每一个论点单独成一个自然段,采用“金字塔结构”: + - 第一句是一个自然段的核心论点(一个核心论点句),论点句需要是一个完整的判断句。 + - 后面进行论证展开(每个论点的背后都有一个完整的逻辑链闭环,完整地展开论点背后的逻辑,并穿插以下三种论据,来补充论证) + 「前提→推理→结论」的三段式链条,推理可以是A->B,也可以是A->B->C,推理的过程依赖于论述的语言和三种论据:①统计数据(近3年权威报告)②典型案例(具名事件)③专家观点(学术/行业权威) + 要求:展开的内容丰富,背后的逻辑链完整严谨准确 + + 3. 价值升华(5%篇幅) + 概括前面的论证主体,然后一句话价值升华 + + 三、专业写作要点 + + 1. 概念界定原则 + - 采用“属+种差”定义法 + - 优先引用国家标准/学术定义 + - 避免循环定义和主观表述 + + 2. 论证规范要求 + ① 数据使用: + - 标明来源机构/年份/样本量 + - 优先选用政府/学术机构数据 + - 动态数据需注明统计时段 + ② 案例选取: + - 具名真实事件(时间+主体+结果) + - 排除虚构假设性案例 + - 中外案例比例建议7:3 + ③论述语言: + - 避免过于学术化 + - 避免过于生活化/口语化 + - 使用精准的,规范严谨的自然语言 + + 3. 语言表达技巧 + - 一篇文章四个自然段,定义与背景一个自然段,每一个论点一个自然段,价值升华一个自然段 + - 每一段控制在400汉字以内,两个论点段控制在300汉字以上 + - 关键术语首次出现加粗 + - 避免修辞性设问 + + 四、常见误区警示 + + 1. 结构错误 + × 混合使用不同论证模型 + × 论点之间存在包含关系 + × 价值升华与论证脱节 + 2. 论据问题 + × 使用过期数据(超过3年) + × 案例缺乏公信力来源 + × 专家引用断章取义 + 3. 表达缺陷 + × 使用绝对化表述 + × 专业术语堆砌 + × 情感化修辞过度 + role-user: user + model: deepseek-chat + frequency_penalty: 0 + max_tokens: 2048 + presence_penalty: 0 + response_format: text + stop: [] + stream: false + stream_options: [] + temperature: 1 + top_p: 1 + tools: [] + tool_choice: [] + logprobs: false + top_logprobs: [] + + # JWT配置 jwt: secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz @@ -26,5 +121,5 @@ jwt: # 服务端口配置 server: - port: 8080 + port: 8000 address: 0.0.0.0 \ No newline at end of file diff --git a/Debate_backend/target/classes/application.yml b/Debate_backend/target/classes/application.yml index f544772..6a5234f 100644 --- a/Debate_backend/target/classes/application.yml +++ b/Debate_backend/target/classes/application.yml @@ -19,6 +19,101 @@ wechat: appid: wxf1f6d7657e01d48a secret: fc356336a118366f27c384079688bc15 +# AI接口配置 +# AI接口配置 +ai: + argument: + url: https://api.deepseek.com/chat/completions + header: + Authorization: "Bearer sk-53428f3b07ff426f8c11d988f649b5e7" + body: + message: + role-sys: system + content-sys: | + 竞技辩论比赛立论撰写指南 + 你是一个华语辩论的爱好者,你要在接下来学习如何完成一场竞技辩论赛立论的撰写,并且成为一个专业的立论专家。当我给你输入任何一道辩题和持方时,你都能模仿我给你提供的数据,写出一篇完整的,自然段语言式的,辩论圈认可的立论。 + 一、立论稿的本质与功能 + 立论稿是辩论中系统阐述己方观点的开篇陈述,需具备: + 1. 明确的定义判准 + 2. 完整的论证体系 + 3. 严谨的逻辑结构 + 4. 充分的论据支撑 + + 二、标准结构(四段式黄金框架) + 1. 定义与背景(15%篇幅) + - 核心概念界定(引用权威定义) + - 讨论范围限定(时空/领域边界) + - 辩题现实意义(社会背景阐述) + - 辩题判断标准(整场比赛的判准) + + 2. 论证主体(80%篇幅,一般为两个论点) + 每一个论点单独成一个自然段,采用“金字塔结构”: + - 第一句是一个自然段的核心论点(一个核心论点句),论点句需要是一个完整的判断句。 + - 后面进行论证展开(每个论点的背后都有一个完整的逻辑链闭环,完整地展开论点背后的逻辑,并穿插以下三种论据,来补充论证) + 「前提→推理→结论」的三段式链条,推理可以是A->B,也可以是A->B->C,推理的过程依赖于论述的语言和三种论据:①统计数据(近3年权威报告)②典型案例(具名事件)③专家观点(学术/行业权威) + 要求:展开的内容丰富,背后的逻辑链完整严谨准确 + + 3. 价值升华(5%篇幅) + 概括前面的论证主体,然后一句话价值升华 + + 三、专业写作要点 + + 1. 概念界定原则 + - 采用“属+种差”定义法 + - 优先引用国家标准/学术定义 + - 避免循环定义和主观表述 + + 2. 论证规范要求 + ① 数据使用: + - 标明来源机构/年份/样本量 + - 优先选用政府/学术机构数据 + - 动态数据需注明统计时段 + ② 案例选取: + - 具名真实事件(时间+主体+结果) + - 排除虚构假设性案例 + - 中外案例比例建议7:3 + ③论述语言: + - 避免过于学术化 + - 避免过于生活化/口语化 + - 使用精准的,规范严谨的自然语言 + + 3. 语言表达技巧 + - 一篇文章四个自然段,定义与背景一个自然段,每一个论点一个自然段,价值升华一个自然段 + - 每一段控制在400汉字以内,两个论点段控制在300汉字以上 + - 关键术语首次出现加粗 + - 避免修辞性设问 + + 四、常见误区警示 + + 1. 结构错误 + × 混合使用不同论证模型 + × 论点之间存在包含关系 + × 价值升华与论证脱节 + 2. 论据问题 + × 使用过期数据(超过3年) + × 案例缺乏公信力来源 + × 专家引用断章取义 + 3. 表达缺陷 + × 使用绝对化表述 + × 专业术语堆砌 + × 情感化修辞过度 + role-user: user + model: deepseek-chat + frequency_penalty: 0 + max_tokens: 2048 + presence_penalty: 0 + response_format: text + stop: [] + stream: false + stream_options: [] + temperature: 1 + top_p: 1 + tools: [] + tool_choice: [] + logprobs: false + top_logprobs: [] + + # JWT配置 jwt: secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz @@ -26,5 +121,5 @@ jwt: # 服务端口配置 server: - port: 8080 + port: 8000 address: 0.0.0.0 \ No newline at end of file diff --git a/Debate_backend/target/classes/com/learning/newdemo/NewDemoApplication.class b/Debate_backend/target/classes/com/learning/newdemo/NewDemoApplication.class index f79830e..388ed9d 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/NewDemoApplication.class and b/Debate_backend/target/classes/com/learning/newdemo/NewDemoApplication.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/common/Result.class b/Debate_backend/target/classes/com/learning/newdemo/common/Result.class index b4ef094..a18ccaf 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/common/Result.class and b/Debate_backend/target/classes/com/learning/newdemo/common/Result.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/config/CorsConfig.class b/Debate_backend/target/classes/com/learning/newdemo/config/CorsConfig.class index 3bbbc45..73e11c0 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/config/CorsConfig.class and b/Debate_backend/target/classes/com/learning/newdemo/config/CorsConfig.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/config/GlobalExceptionHandler.class b/Debate_backend/target/classes/com/learning/newdemo/config/GlobalExceptionHandler.class index d8e9c0a..da8a936 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/config/GlobalExceptionHandler.class and b/Debate_backend/target/classes/com/learning/newdemo/config/GlobalExceptionHandler.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/config/RestTemplateConfig.class b/Debate_backend/target/classes/com/learning/newdemo/config/RestTemplateConfig.class index c5af04f..f96619c 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/config/RestTemplateConfig.class and b/Debate_backend/target/classes/com/learning/newdemo/config/RestTemplateConfig.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/controller/WxAIController.class b/Debate_backend/target/classes/com/learning/newdemo/controller/WxAIController.class new file mode 100644 index 0000000..3e223b5 Binary files /dev/null and b/Debate_backend/target/classes/com/learning/newdemo/controller/WxAIController.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/controller/WxLoginController.class b/Debate_backend/target/classes/com/learning/newdemo/controller/WxLoginController.class index 13f32a4..bf1946c 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/controller/WxLoginController.class and b/Debate_backend/target/classes/com/learning/newdemo/controller/WxLoginController.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/entity/WxUser.class b/Debate_backend/target/classes/com/learning/newdemo/entity/WxUser.class index e8c6d59..2727c47 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/entity/WxUser.class and b/Debate_backend/target/classes/com/learning/newdemo/entity/WxUser.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/mapper/WxUserMapper.class b/Debate_backend/target/classes/com/learning/newdemo/mapper/WxUserMapper.class index fae010a..a9b6094 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/mapper/WxUserMapper.class and b/Debate_backend/target/classes/com/learning/newdemo/mapper/WxUserMapper.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/service/WxArgumentService.class b/Debate_backend/target/classes/com/learning/newdemo/service/WxArgumentService.class new file mode 100644 index 0000000..b8934c4 Binary files /dev/null and b/Debate_backend/target/classes/com/learning/newdemo/service/WxArgumentService.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/service/WxUserService.class b/Debate_backend/target/classes/com/learning/newdemo/service/WxUserService.class index ab1450c..7676664 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/service/WxUserService.class and b/Debate_backend/target/classes/com/learning/newdemo/service/WxUserService.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/service/impl/WxArgumentServiceImpl.class b/Debate_backend/target/classes/com/learning/newdemo/service/impl/WxArgumentServiceImpl.class new file mode 100644 index 0000000..9ef9f25 Binary files /dev/null and b/Debate_backend/target/classes/com/learning/newdemo/service/impl/WxArgumentServiceImpl.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/service/impl/WxUserServiceImpl.class b/Debate_backend/target/classes/com/learning/newdemo/service/impl/WxUserServiceImpl.class index a6554f9..8ff3f17 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/service/impl/WxUserServiceImpl.class and b/Debate_backend/target/classes/com/learning/newdemo/service/impl/WxUserServiceImpl.class differ diff --git a/Debate_backend/target/classes/com/learning/newdemo/util/JwtUtil.class b/Debate_backend/target/classes/com/learning/newdemo/util/JwtUtil.class index fa44357..b6c742c 100644 Binary files a/Debate_backend/target/classes/com/learning/newdemo/util/JwtUtil.class and b/Debate_backend/target/classes/com/learning/newdemo/util/JwtUtil.class differ