立论和复盘

main
chantouRichard 3 months ago
commit c7319a564d

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -8,6 +8,7 @@ import java.io.Serializable;
* API * API
*/ */
@Data @Data
// Serializable接口的作用是标记当前类可以通过序列化在网络中传播
public class Result<T> implements Serializable { public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

@ -0,0 +1,86 @@
package com.learning.newdemo.controller;
import com.learning.newdemo.common.Result;
import com.learning.newdemo.service.WxArgumentService;
import com.learning.newdemo.service.WxReviewService;
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;
@Autowired
private WxReviewService wxReviewService;
private String topic;
private String stance;
private String content;
@PostMapping("/argument")
public Result<Map<String, Object>> getArgument(@RequestBody Map<String, String> params){
topic = params.get("topic");
stance = params.get("stance");
if(topic == null || stance == null){
return Result.error("立论主题或者内容为空");
}
log.info("请求内容: {}", params);
try {
String argument = wxArgumentService.getArgument(topic, stance);
if (argument == null) {
return Result.error("立论获取失败");
}
Map<String, Object> data = new HashMap<>();
data.put("argument", argument);
// 查看data
log.info("立论获取成功:{}", argument);
return Result.success(data);
}catch (Exception e){
log.error("立论获取失败", e);
return Result.error("立论获取失败:" + e.getMessage());
}
}
@PostMapping("/review")
public Result<Map<String, Object>> review(@RequestBody Map<String, String> params){
log.info("请求内容: {}", params);
content = params.get("content");
try {
String review = wxReviewService.getReview(content);
if (review == null) {
return Result.error("复盘获取失败");
}
Map<String, Object> data = new HashMap<>();
data.put("review", review);
// 查看data
log.info("复盘获取成功:{}", review);
return Result.success(data);
}catch (Exception e){
log.error("复盘获取失败", e);
return Result.error("复盘获取失败:" + e.getMessage());
}
}
}

@ -0,0 +1,9 @@
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 WxReviewService {
String getReview(String content);
}

@ -0,0 +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");
}
}

@ -0,0 +1,91 @@
package com.learning.newdemo.service.impl;
import com.learning.newdemo.service.WxReviewService;
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 WxReviewServiceImpl implements WxReviewService {
private final RestTemplate restTemplate;
@Value("${ai.argument.header.Authorization}") private String authorizationHeader;
@Value("${ai.argument.body.message.role-sys}") private String roleSys;
@Value("${ai.review.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 WxReviewServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public String getReview(String content) {
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\": \"" + content + "\""
+ "}"
+ "],"
+ "\"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");
}
}

@ -43,7 +43,12 @@ public class WxUserServiceImpl implements WxUserService {
+ "&js_code=" + code + "&js_code=" + code
+ "&grant_type=authorization_code"; + "&grant_type=authorization_code";
log.info("请求微信接口URL: {}", url);
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class); ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
String responseBody = response.getBody();
log.info("微信接口返回: {}", responseBody);
JSONObject json = JSONObject.parseObject(response.getBody()); JSONObject json = JSONObject.parseObject(response.getBody());
// 获取openid // 获取openid

@ -19,6 +19,214 @@ wechat:
appid: wxf1f6d7657e01d48a appid: wxf1f6d7657e01d48a
secret: fc356336a118366f27c384079688bc15 secret: fc356336a118366f27c384079688bc15
# 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
stream: false
temperature: 1
top_p: 1
tool_choice: "none"
logprobs: false
review:
url: https://api.deepseek.com/chat/completions
header:
Authorization: "Bearer sk-53428f3b07ff426f8c11d988f649b5e7"
body:
message:
role-sys: system
content-sys: |
评委指南
你是一个华语辩论人类评委。这是你的竞技辩论赛评委评判指南,你需要基于这个指南,完成辩论比赛的评判:以下为综合多篇辩论赛评委指南与培训资料整理的**完整评委点评操作手册**,严格遵循客观性、细节化与责任量化原则:
---
一、开场与礼节
1. 礼仪问候
- 向主办方、主席、辩手及观众致谢,肯定比赛价值
- 示例:“感谢主办方提供交流平台,双方辩手为准备比赛付出的努力值得掌声。”
2. 判准说明
- 明确告知评判标准(如说服力优先/逻辑完整性优先)及心证介入程度
- 示例:“本场以‘有效回应率’为核心判准,仅介入基础常识性心证(如历史事实),价值观争议由辩手自行论证。”
---
二、立论拆解与记录(尽可能详细和完整,不要主观概括)
1. 正方立论复现
- 定义:逐字记录核心概念界定(如“宿命=结构性高概率风险”)
- 框架:分论点逻辑链(例:认知落差→自我透明错觉→时空差异)
- 实证:标注数据来源(如《科学》杂志研究)及案例适用性(如数学家构建零误解语言失败)
2. 反方立论复现
- 定义:差异化界定(如“宿命=必然不可改变属性”)
- 框架:论证路径(例:方法论规避→技术干预→价值主张)
- 实证记录反例类型如韩国网络实名制误解率下降43%)及数据完整性
记录工具建议:使用分栏表格(如下),红笔标注未论证部分
维度
正方内容
反方内容
定义
结构性高概率风险
必然不可改变属性
核心论点
三阶机理(认知落差→自我透明错觉→时空差异)
双重路径(开放式表达+算法过滤)
---
三、攻防细节实录(尽可能详细和完整,不要主观概括)
1. 关键交锋逐句记录
- 定义战:
- 反方质疑:“若宿命=高概率30%文盲率是否构成宿命?”→ 正方回应:“宿命需机理不可逆性,文盲可通过教育改变,时空差异无法消除”(引用联合国扫盲数据)→ **有效性**:正方回应有效(守住机理标准),反方未追击“不可逆性”自洽性
- 实证战:
- 反方引用韩国案例,正方质疑数据覆盖范围(未包含社交媒体)→ 反方补充首尔大学报告第17页样本说明→ **有效性**:反方数据完整,但未回应“算法过滤导致表达萎缩”衍生问题
2. 无效回应标注
- 正方四辩未量化“高概率阈值”如87%是否达标),导致机理说服力下降
- 反方混淆“多元解读”与“误解”界限,未区分艺术与日常表达场景
记录工具建议时间轴标记法12:30-13:00 反方三辩未回应正方质询)
---
四、论证责任完成度量化(不是简单的量化,需要评估核心战场和挑战,不是所有挑战都是一样的权重)
1. 正方责任评估
- 完成项三阶机理论证60%),定义防御(回应文盲类比)
- 未完成项未解释“30% vs 87%”阈值差异,未反驳反方群体必然性关联性质疑
2. 反方责任评估
- 完成项证伪“绝对必然性”50%),韩国案例实证完整
- 未完成项:未覆盖日常表达场景(如医疗告知需精确语义),未衔接实证与价值主张
量化公式参考:
单方完成度 = (有效回应数 ÷ 总挑战数)× 100%
正方回应反方5次挑战中的3次 → 完成度60%
---
五、胜负判定模板
1. 战场归属统计
战场
正方得分
反方得分
依据
定义战
守住机理不可逆性
实证战
韩国案例数据完整但场景受限
价值战
双方未衔接实证与价值
2. 终局判词“正方通过机理不可逆性论证更贴近宿命本质,反方实证覆盖不足导致价值断裂,故判正方胜。”
---
六、改进建议指南
1. 正方优化方向
- 补充“高概率阈值”学术界定(如引用社会心理学“群体认知偏差”研究)
- 深化价值自洽:回应“宿命论是否导致消极躺平”(例:加缪式存在主义勇气)
2. 反方优化方向
- 区分艺术与日常表达场景,补充欧盟《数字服务法》平衡性案例
- 实证延伸:量化“开放式表达促进社会创新”数据(如专利合作沟通案例)
---
七、评委禁忌清单
1. 表述禁区
- 绝对化断言:“反方立论完全错误”
- 主观情感:“我被正方四辩的煽情打动”
2. 程序禁区
- 提前暗示结果:“反方某论点已决定胜负”
- 介入未挑战定义:“默认反方扩大外延无效”
---
八、工具包与训练建议
1. 记录工具:康奈尔笔记法(主栏记录/副栏批注)、多色荧光笔标注攻防有效性
2. 判准校准训练观摩5场不同风格比赛哲理辩/政策辩),检验判准普适性
3. 反馈话术库:
- 建设性批评:“建议补充**世界卫生组织沟通指南**强化数据权威性”
- 价值升华:“辩论如苏格拉底产婆术,助真理诞生而非制造对立”
---
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配置
jwt: jwt:
secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz

@ -19,6 +19,214 @@ wechat:
appid: wxf1f6d7657e01d48a appid: wxf1f6d7657e01d48a
secret: fc356336a118366f27c384079688bc15 secret: fc356336a118366f27c384079688bc15
# 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
stream: false
temperature: 1
top_p: 1
tool_choice: "none"
logprobs: false
review:
url: https://api.deepseek.com/chat/completions
header:
Authorization: "Bearer sk-53428f3b07ff426f8c11d988f649b5e7"
body:
message:
role-sys: system
content-sys: |
评委指南
你是一个华语辩论人类评委。这是你的竞技辩论赛评委评判指南,你需要基于这个指南,完成辩论比赛的评判:以下为综合多篇辩论赛评委指南与培训资料整理的**完整评委点评操作手册**,严格遵循客观性、细节化与责任量化原则:
---
一、开场与礼节
1. 礼仪问候
- 向主办方、主席、辩手及观众致谢,肯定比赛价值
- 示例:“感谢主办方提供交流平台,双方辩手为准备比赛付出的努力值得掌声。”
2. 判准说明
- 明确告知评判标准(如说服力优先/逻辑完整性优先)及心证介入程度
- 示例:“本场以‘有效回应率’为核心判准,仅介入基础常识性心证(如历史事实),价值观争议由辩手自行论证。”
---
二、立论拆解与记录(尽可能详细和完整,不要主观概括)
1. 正方立论复现
- 定义:逐字记录核心概念界定(如“宿命=结构性高概率风险”)
- 框架:分论点逻辑链(例:认知落差→自我透明错觉→时空差异)
- 实证:标注数据来源(如《科学》杂志研究)及案例适用性(如数学家构建零误解语言失败)
2. 反方立论复现
- 定义:差异化界定(如“宿命=必然不可改变属性”)
- 框架:论证路径(例:方法论规避→技术干预→价值主张)
- 实证记录反例类型如韩国网络实名制误解率下降43%)及数据完整性
记录工具建议:使用分栏表格(如下),红笔标注未论证部分
维度
正方内容
反方内容
定义
结构性高概率风险
必然不可改变属性
核心论点
三阶机理(认知落差→自我透明错觉→时空差异)
双重路径(开放式表达+算法过滤)
---
三、攻防细节实录(尽可能详细和完整,不要主观概括)
1. 关键交锋逐句记录
- 定义战:
- 反方质疑:“若宿命=高概率30%文盲率是否构成宿命?”→ 正方回应:“宿命需机理不可逆性,文盲可通过教育改变,时空差异无法消除”(引用联合国扫盲数据)→ **有效性**:正方回应有效(守住机理标准),反方未追击“不可逆性”自洽性
- 实证战:
- 反方引用韩国案例,正方质疑数据覆盖范围(未包含社交媒体)→ 反方补充首尔大学报告第17页样本说明→ **有效性**:反方数据完整,但未回应“算法过滤导致表达萎缩”衍生问题
2. 无效回应标注
- 正方四辩未量化“高概率阈值”如87%是否达标),导致机理说服力下降
- 反方混淆“多元解读”与“误解”界限,未区分艺术与日常表达场景
记录工具建议时间轴标记法12:30-13:00 反方三辩未回应正方质询)
---
四、论证责任完成度量化(不是简单的量化,需要评估核心战场和挑战,不是所有挑战都是一样的权重)
1. 正方责任评估
- 完成项三阶机理论证60%),定义防御(回应文盲类比)
- 未完成项未解释“30% vs 87%”阈值差异,未反驳反方群体必然性关联性质疑
2. 反方责任评估
- 完成项证伪“绝对必然性”50%),韩国案例实证完整
- 未完成项:未覆盖日常表达场景(如医疗告知需精确语义),未衔接实证与价值主张
量化公式参考:
单方完成度 = (有效回应数 ÷ 总挑战数)× 100%
正方回应反方5次挑战中的3次 → 完成度60%
---
五、胜负判定模板
1. 战场归属统计
战场
正方得分
反方得分
依据
定义战
守住机理不可逆性
实证战
韩国案例数据完整但场景受限
价值战
双方未衔接实证与价值
2. 终局判词“正方通过机理不可逆性论证更贴近宿命本质,反方实证覆盖不足导致价值断裂,故判正方胜。”
---
六、改进建议指南
1. 正方优化方向
- 补充“高概率阈值”学术界定(如引用社会心理学“群体认知偏差”研究)
- 深化价值自洽:回应“宿命论是否导致消极躺平”(例:加缪式存在主义勇气)
2. 反方优化方向
- 区分艺术与日常表达场景,补充欧盟《数字服务法》平衡性案例
- 实证延伸:量化“开放式表达促进社会创新”数据(如专利合作沟通案例)
---
七、评委禁忌清单
1. 表述禁区
- 绝对化断言:“反方立论完全错误”
- 主观情感:“我被正方四辩的煽情打动”
2. 程序禁区
- 提前暗示结果:“反方某论点已决定胜负”
- 介入未挑战定义:“默认反方扩大外延无效”
---
八、工具包与训练建议
1. 记录工具:康奈尔笔记法(主栏记录/副栏批注)、多色荧光笔标注攻防有效性
2. 判准校准训练观摩5场不同风格比赛哲理辩/政策辩),检验判准普适性
3. 反馈话术库:
- 建设性批评:“建议补充**世界卫生组织沟通指南**强化数据权威性”
- 价值升华:“辩论如苏格拉底产婆术,助真理诞生而非制造对立”
---
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配置
jwt: jwt:
secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz secret: yoursecretkey123456789abcdefghijklmnopqrstuvwxyz

@ -2,17 +2,143 @@
<view class="argument-component"> <view class="argument-component">
<view class="content-card"> <view class="content-card">
<view class="card-title">立论功能</view> <view class="card-title">立论功能</view>
<view class="card-content"> <view class="card-content">在这里可以进行辩题立论和论点整理</view>
在这里可以进行辩题立论和论点整理
</view> </view>
<!-- 聊天展示区 -->
<scroll-view
class="chat-area"
scroll-y
:scroll-into-view="scrollToView"
scroll-with-animation
>
<view
v-for="(msg, index) in messages"
:key="index"
:id="'msg' + index"
class="chat-message"
:class="msg.role === 'user' ? 'from-user' : 'from-ai'"
>
<view class="bubble">
<block v-if="msg.loading">
<view class="dot-flashing"></view>
</block>
<block v-else>
{{ msg.content }}
</block>
</view>
</view>
</scroll-view>
<!-- 输入框与发送按钮 -->
<view class="chat-input">
<view class="input-group">
<input
class="input-box"
type="text"
v-model="position"
placeholder="请输入论方,例如:正方"
/>
<textarea
class="textarea-box"
v-model="question"
placeholder="请输入辩题,例如:应不应该取消作业"
auto-height
/>
</view>
<button class="send-button" @click="sendMessage()"></button>
</view> </view>
</view> </view>
</template> </template>
<script>
export default {
data() {
return {
input: "",
messages: [],
scrollToView: "",
position: "",
question: "",
};
},
methods: {
async sendMessage() {
//
this.messages.push({
role: "user",
content: this.position + " " + this.question,
});
this.scrollToBottom();
// AI loading
const aiIndex = this.messages.length;
this.messages.push({ role: "ai", content: "", loading: true });
this.scrollToBottom();
// AI
const reply = await this.callAI(this.position, this.question);
// loading AI
this.messages.splice(aiIndex, 1, { role: "ai", content: reply });
this.scrollToBottom();
},
async callAI(topic, stance) {
this.position = "";
this.question = "";
return new Promise((resolve, reject) => {
console.log("callAI:", topic, stance);
uni.request({
url: "http://localhost:8080/api/ai/argument", // URL
method: "POST",
header: {
"Content-Type": "application/json",
},
data: {
topic: topic,
stance: stance,
},
success: (res) => {
console.log("res:", res);
let reviewJson = JSON.parse(res.data.data.argument);
if (res.statusCode === 200 && res.data.code === 200) {
resolve(
reviewJson.choices[0].message.content || "AI 没有返回有效内容"
);
} else {
reject("请求失败:" + (res.data.msg || "未知错误"));
}
},
fail: (err) => {
reject("请求失败:" + err.errMsg);
},
});
});
},
scrollToBottom() {
this.$nextTick(() => {
this.scrollToView = "msg" + (this.messages.length - 1);
});
},
},
};
</script>
<style scoped> <style scoped>
.argument-component { .argument-component {
width: 100%; width: 100%;
padding: 20rpx; padding: 20rpx;
display: flex;
flex-direction: column;
height: 78vh;
background: linear-gradient(135deg, #2c3e50, #4ca1af);
overflow-x: hidden; /* 禁止横向滚动 */
box-sizing: border-box; /* 避免 padding 导致溢出 */
} }
.content-card { .content-card {
@ -20,7 +146,7 @@
border-radius: 20rpx; border-radius: 20rpx;
padding: 30rpx; padding: 30rpx;
width: 90%; width: 90%;
margin: 0 auto; margin: 0 auto 30rpx;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
} }
@ -35,4 +161,145 @@
font-size: 28rpx; font-size: 28rpx;
color: rgba(255, 255, 255, 0.8); color: rgba(255, 255, 255, 0.8);
} }
/* 聊天区域 */
.chat-area {
flex: 1;
width: 90%;
margin: 0 auto;
background-color: rgba(255, 255, 255, 0.05);
border-radius: 20rpx;
padding: 20rpx;
overflow-y: auto;
}
/* 消息通用样式 */
.chat-message {
display: flex;
margin-bottom: 20rpx;
}
/* 用户消息靠右 */
.from-user {
justify-content: flex-end;
}
/* AI消息靠左 */
.from-ai {
justify-content: flex-start;
}
/* 气泡样式 */
.bubble {
max-width: 70%;
padding: 20rpx;
border-radius: 20rpx;
font-size: 28rpx;
line-height: 1.6;
word-break: break-word;
}
/* 用户气泡颜色 */
.from-user .bubble {
background-color: #00c4ff;
color: white;
border-bottom-right-radius: 0;
}
/* AI气泡颜色 */
.from-ai .bubble {
background-color: #ffd54f;
color: #333;
border-bottom-left-radius: 0;
min-width: 80px;
}
/* 输入区域 */
.chat-input {
display: flex;
padding: 20rpx;
background-color: rgba(255, 255, 255, 0.05);
border-top: 1rpx solid #ccc;
align-items: flex-end;
}
.input-group {
flex: 1;
display: flex;
flex-direction: column;
gap: 10rpx;
}
.input-box {
background-color: #fff;
border-radius: 10rpx;
padding: 10rpx 20rpx;
margin-bottom: 20rpx;
font-size: 28rpx;
border: none;
}
.textarea-box {
background-color: #fff;
border-radius: 10rpx;
padding: 10rpx 20rpx;
font-size: 28rpx;
min-height: 80rpx;
border: none;
}
.send-button {
margin-left: 20rpx;
background-color: #00bcd4;
color: #fff;
border-radius: 10rpx;
padding: 20rpx;
font-size: 28rpx;
white-space: nowrap;
}
/* AI loading 动画 */
.dot-flashing {
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #333;
animation: dotFlashing 1s infinite linear alternate;
position: relative;
margin-left: auto;
margin-right: auto;
}
.dot-flashing::before,
.dot-flashing::after {
content: "";
display: inline-block;
position: absolute;
top: 0;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #333;
}
.dot-flashing::before {
left: -30rpx;
animation: dotFlashing 1s infinite linear alternate;
animation-delay: 0.2s;
}
.dot-flashing::after {
left: 30rpx;
animation: dotFlashing 1s infinite linear alternate;
animation-delay: 0.4s;
}
@keyframes dotFlashing {
0% {
background-color: #333;
}
50%,
100% {
background-color: rgba(51, 51, 51, 0.3);
}
}
</style> </style>

@ -0,0 +1,295 @@
<template>
<view class="argument-component">
<view class="content-card">
<view class="card-title">复盘功能</view>
<view class="card-content">在这里可以进行辩论过程的复盘</view>
</view>
<!-- 聊天展示区 -->
<scroll-view
class="chat-area"
scroll-y
:scroll-into-view="scrollToView"
scroll-with-animation
>
<view
v-for="(msg, index) in messages"
:key="index"
:id="'msg' + index"
class="chat-message"
:class="msg.role === 'user' ? 'from-user' : 'from-ai'"
>
<view class="bubble">
<block v-if="msg.loading">
<view class="dot-flashing"></view>
</block>
<block v-else>
{{ msg.content }}
</block>
</view>
</view>
</scroll-view>
<!-- 输入框与发送按钮 -->
<view class="chat-input">
<view class="input-group">
<textarea
class="textarea-box"
v-model="content"
placeholder="请输入辩论的过程"
auto-height
/>
</view>
<button class="send-button" @click="sendMessage()"></button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
input: "",
messages: [],
scrollToView: "",
content: "",
};
},
methods: {
async sendMessage() {
//
this.messages.push({
role: "user",
content: this.content,
});
this.scrollToBottom();
// AI loading
const aiIndex = this.messages.length;
this.messages.push({ role: "ai", content: "", loading: true });
this.scrollToBottom();
// AI
const reply = await this.callAI(this.content);
// loading AI
this.messages.splice(aiIndex, 1, { role: "ai", content: reply });
this.scrollToBottom();
},
async callAI(content) {
this.content = "";
return new Promise((resolve, reject) => {
console.log("callAI:", content);
uni.request({
url: "http://localhost:8080/api/ai/review",
method: "POST",
header: {
"Content-Type": "application/json",
},
data: {
content: content
},
success: (res) => {
console.log("res:", res);
let reviewJson = JSON.parse(res.data.data.review);
if (res.statusCode === 200 && res.data.code === 200) {
resolve(
reviewJson.choices[0].message.content || "AI 没有返回有效内容"
);
} else {
reject("请求失败:" + (res.data.msg || "未知错误"));
}
},
fail: (err) => {
reject("请求失败:" + err.errMsg);
},
});
});
},
scrollToBottom() {
this.$nextTick(() => {
this.scrollToView = "msg" + (this.messages.length - 1);
});
},
},
};
</script>
<style scoped>
.argument-component {
width: 100%;
padding: 20rpx;
display: flex;
flex-direction: column;
height: 78vh;
background: linear-gradient(135deg, #2c3e50, #337fc6);
overflow-x: hidden; /* 禁止横向滚动 */
box-sizing: border-box; /* 避免 padding 导致溢出 */
}
.content-card {
background-color: rgba(255, 255, 255, 0.1);
border-radius: 20rpx;
padding: 30rpx;
width: 90%;
margin: 0 auto 30rpx;
backdrop-filter: blur(10px);
}
.card-title {
font-size: 36rpx;
color: #ffffff;
font-weight: bold;
margin-bottom: 20rpx;
}
.card-content {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
/* 聊天区域 */
.chat-area {
flex: 1;
width: 90%;
margin: 0 auto;
background-color: rgba(255, 255, 255, 0.05);
border-radius: 20rpx;
padding: 20rpx;
overflow-y: auto;
}
/* 消息通用样式 */
.chat-message {
display: flex;
margin-bottom: 20rpx;
}
/* 用户消息靠右 */
.from-user {
justify-content: flex-end;
}
/* AI消息靠左 */
.from-ai {
justify-content: flex-start;
}
/* 气泡样式 */
.bubble {
max-width: 70%;
padding: 20rpx;
border-radius: 20rpx;
font-size: 28rpx;
line-height: 1.6;
word-break: break-word;
}
/* 用户气泡颜色 */
.from-user .bubble {
background-color: #00c4ff;
color: white;
border-bottom-right-radius: 0;
}
/* AI气泡颜色 */
.from-ai .bubble {
background-color: #ffd54f;
color: #333;
border-bottom-left-radius: 0;
min-width: 80px;
}
/* 输入区域 */
.chat-input {
display: flex;
padding: 20rpx;
background-color: rgba(255, 255, 255, 0.05);
border-top: 1rpx solid #ccc;
align-items: flex-end;
}
.input-group {
flex: 1;
display: flex;
flex-direction: column;
gap: 10rpx;
}
.input-box {
background-color: #fff;
border-radius: 10rpx;
padding: 10rpx 20rpx;
margin-bottom: 20rpx;
font-size: 28rpx;
border: none;
}
.textarea-box {
background-color: #fff;
border-radius: 10rpx;
padding: 10rpx 20rpx;
font-size: 28rpx;
min-height: 80rpx;
border: none;
}
.send-button {
margin-left: 20rpx;
background-color: #00bcd4;
color: #fff;
border-radius: 10rpx;
padding: 20rpx;
font-size: 28rpx;
white-space: nowrap;
}
/* AI loading 动画 */
.dot-flashing {
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #333;
animation: dotFlashing 1s infinite linear alternate;
position: relative;
margin-left: auto;
margin-right: auto;
}
.dot-flashing::before,
.dot-flashing::after {
content: "";
display: inline-block;
position: absolute;
top: 0;
width: 20rpx;
height: 20rpx;
border-radius: 50%;
background-color: #333;
}
.dot-flashing::before {
left: -30rpx;
animation: dotFlashing 1s infinite linear alternate;
animation-delay: 0.2s;
}
.dot-flashing::after {
left: 30rpx;
animation: dotFlashing 1s infinite linear alternate;
animation-delay: 0.4s;
}
@keyframes dotFlashing {
0% {
background-color: #333;
}
50%,
100% {
background-color: rgba(51, 51, 51, 0.3);
}
}
</style>

@ -28,7 +28,7 @@ import { ref } from 'vue';
// //
import PageOfHome from '../../components/HomeCom.vue'; import PageOfHome from '../../components/HomeCom.vue';
import PageOfArgument from '../../components/ArgumentCom.vue'; import PageOfArgument from '../../components/ArgumentCom.vue';
// import PageOfReview from '../../components/ReviewCom.vue'; import PageOfReview from '../../components/ReviewCom.vue';
// import PageOfDebate from '../../components/DebateCom.vue'; // import PageOfDebate from '../../components/DebateCom.vue';
// //

Loading…
Cancel
Save