From cbbc862d564d61653982df453e0e417bb4704684 Mon Sep 17 00:00:00 2001 From: Heife <2044384845@qq.com> Date: Wed, 9 Apr 2025 16:58:32 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AB=8B=E8=AE=BA=E5=90=8E=E7=AB=AF=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../newdemo/controller/WxAIController.java | 4 + .../service/impl/WxArgumentServiceImpl.java | 175 ++++++------------ .../src/main/resources/application.yml | 9 +- Debate_backend/target/classes/application.yml | 7 +- .../newdemo/controller/WxAIController.class | Bin 3184 -> 3287 bytes .../service/impl/WxArgumentServiceImpl.class | Bin 5206 -> 5480 bytes .../service/impl/WxUserServiceImpl.class | Bin 4356 -> 4277 bytes 7 files changed, 67 insertions(+), 128 deletions(-) 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 index 671b534..80db15b 100644 --- a/Debate_backend/src/main/java/com/learning/newdemo/controller/WxAIController.java +++ b/Debate_backend/src/main/java/com/learning/newdemo/controller/WxAIController.java @@ -29,6 +29,7 @@ public class WxAIController { topic = params.get("topic"); stance = params.get("stance"); + if(topic == null || stance == null){ return Result.error("立论主题或者内容为空"); } @@ -41,6 +42,9 @@ public class WxAIController { Map data = new HashMap<>(); data.put("argument", argument); + // 查看data + log.info("立论获取成功:{}", argument); + return Result.success(data); }catch (Exception e){ log.error("立论获取失败", e); 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 index 2050b1c..cb6499b 100644 --- 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 @@ -3,7 +3,11 @@ 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.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; @@ -11,66 +15,23 @@ import org.springframework.web.client.RestTemplate; @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; + @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; @@ -78,73 +39,57 @@ public class WxArgumentServiceImpl implements WxArgumentService { @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 - ); + // 构建请求体,使用字符串拼接 + 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 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); + } 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"); + } +} \ No newline at end of file diff --git a/Debate_backend/src/main/resources/application.yml b/Debate_backend/src/main/resources/application.yml index 6a5234f..44b3272 100644 --- a/Debate_backend/src/main/resources/application.yml +++ b/Debate_backend/src/main/resources/application.yml @@ -19,7 +19,6 @@ wechat: appid: wxf1f6d7657e01d48a secret: fc356336a118366f27c384079688bc15 -# AI接口配置 # AI接口配置 ai: argument: @@ -103,15 +102,11 @@ ai: max_tokens: 2048 presence_penalty: 0 response_format: text - stop: [] stream: false - stream_options: [] temperature: 1 top_p: 1 - tools: [] - tool_choice: [] + tool_choice: "none" logprobs: false - top_logprobs: [] # JWT配置 @@ -121,5 +116,5 @@ jwt: # 服务端口配置 server: - port: 8000 + port: 8080 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 6a5234f..f81e75a 100644 --- a/Debate_backend/target/classes/application.yml +++ b/Debate_backend/target/classes/application.yml @@ -19,7 +19,6 @@ wechat: appid: wxf1f6d7657e01d48a secret: fc356336a118366f27c384079688bc15 -# AI接口配置 # AI接口配置 ai: argument: @@ -103,15 +102,11 @@ ai: max_tokens: 2048 presence_penalty: 0 response_format: text - stop: [] stream: false - stream_options: [] temperature: 1 top_p: 1 - tools: [] - tool_choice: [] + tool_choice: "none" logprobs: false - top_logprobs: [] # JWT配置 diff --git a/Debate_backend/target/classes/com/learning/newdemo/controller/WxAIController.class b/Debate_backend/target/classes/com/learning/newdemo/controller/WxAIController.class index 3e223b511c0b6bfb27ea9781d9e5f0d956656436..afbe62a725f7d131f1d7ea9306236fcd69ff985b 100644 GIT binary patch delta 769 zcmX|;TTj$*5XFE0ZK2)L09oR4U&V-^uA+cJK@=5SR1mLt0Rcf+xyZ`JE8uz;G*Oc# zKKSAXATc0`;zs=dz8d2vKz&mmd^75_5ZknK=A84N&P;z~ea^N%{7JkAs+pX%G|lo8 zV2jOGDxJ8N8!_3Y$ox9}@Y{>Tw@0rR9zXpu`DEe2^Y3q;jZLJmogD@>Happ+NRJIi zOGXBI%KJ(hV$o>#utM)0?1?FgoOfC%qp7p6yKA&+O|wNlwKjF^aWb`ts(0G8pyd|Z zXS0I+PC_d&BQ)9^pvn2E6(=9EIm{7fxn7rYjAn!5HYYea7t^bBHRep4d8rc?*NGe4 zaGf`uPv%Gcj-t>}{=#H~dy0_2kn_tQ+$^KXygpV@h~kvsWQi>vXR^$TnO@X{Px91O zr^X7FonG=n25o|E(Gf>G9TF95IU`xCz!o%g;ijA^t0VrBia=HP4b>X!=h;2e=n`Qe z_G*M*(U9OE%#$}GU6s7l4qMj SjLUP4TarqD+~zL#$^HkSG<`1s delta 752 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 literal 5206 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 delta 2021 zcmZWq+gDUo82{}#bIzGLa}XRv9ncX_K(14QrCby=Qw${Vf>(5a<1jeP(99@a8}FKx zMq5m?EHllL6cqvQJ!z}eYV{}d5ZFU6zVy_}zI_I1r7X_=_WADn_x<*nTNwv4lYaW= z&I14y7*JthDCSS?DcwzOmkKLGQoDDX*AwsteV)4JcB3V#Lg8N3QzHdJJ_ct^DD3k@ z0-Hq%~{}M*ST|b#R+M;%^QZRl#5=>W%tC!H5V6ggTl-TRe-6pb_>) zjn=a6-BbB-wJTGJ7%gEV$}oAxt}dgc%^NN1@CW_g&d#E^We<{-968 zLM&4826tPE=nQXSF|V;~wO8XU6-ya%c!p&HzhX%yTMcUYUzX{tj;Bg#NUV!e(HXkt+PkwqPy(H$nFYi-!X zldNf}bJ47$1r-dk5e|pK8X;ro*bELR*ZW4V^@XICf9Y+#SB(GkkCV@X(NeE-We$Tk?35#m)V)E~(hcljMmi4Y-8{ z%zv@<@OJyo6fvKJI+8KLfx|ee;t0b`v+!?n@)RBKfp|JDVg!i13wG3*2&j0U5hI@3 zGZQr&L#|kk>o|drc$t!IJB*KYaGd0RrC2A}y0)*37-3=#@0KU>X-Wc5*5+s;=u;hM z@fp9QWKz&M9bZt;ugavH^Tgqiv;8Bd`ktJ;JaTkUuw&n~`0?lf;ZPTyja756)@sx6 zEv~5ej#oKyXkI1g*M5cWL?Hwe?(UTZK5*disFB_a>AV5bAB1?*yg{J$G zj_3;(GgCizl&OJKq><|s3d@MfALqe+RRG+8dbee68R%=13sz zyaH#XbRW_H7Az|qz>*(OS!xw7%Uo8|XH+?aw@YQ0>|8Z~)uoC{c?5?`8Nj+T7%#jx zy6WZI@X`eO@`S#%k#e_*U3;HdF+>&L5oYQR2q1Y?UvtlV`V;6Q4ILir@M$#$R zOGDa2RV`E(W{!B|UW(jD8V{sr*aTGtQ&CC(F%{M3uAWvP;hA7e+$vn6*iTV1qlN_d z^c|qoV&bPsN+e4Nh6DMxama$&g2%|di(_jB@j-1t{(w1{0|ZOA1p=)xw?2xKOi0|| zS&42FgY