Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ public class TaskRegistrarAutoConfig implements EnvironmentAware, SchedulingConf
public void setEnvironment(Environment environment) {
String prefix = "chatbot-api.";
String launchListStr = environment.getProperty(prefix + "launchList");
if (StringUtils.isEmpty(launchListStr)) return;
if (StringUtils.isEmpty(launchListStr)) {
return;
}
for (String groupKey : launchListStr.split(",")) {
Map<String, Object> taskGroupProps = PropertyUtil.handle(environment, prefix + groupKey, Map.class);
taskGroupMap.put(groupKey, taskGroupProps);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package cn.bugstack.chatbot.api.domain.ai.model.aggregates;

import cn.bugstack.chatbot.api.domain.ai.model.vo.CompletionModel;
import cn.bugstack.chatbot.api.domain.ai.model.vo.Message;

/**
* AI Question
*
* @author Ronnyz
* @since 2023/9/30
*/
public class AIQuestion {
private CompletionModel completion;

public AIQuestion(CompletionModel completion) {
this.completion = completion;
}

public AIQuestion(String model, String content) {
Message systemMsg = new Message("system", "你是一位 AI 咨询师,你的计算机技术能力超强,能够为我提供准确的解答和建议,无论我的问题是生活问题、编程问题还是其他领域的问题,你都能够提供详尽的解释和回答。");
Message userMsg = new Message("user", content);
Message[] msgs = new Message[2];
msgs[0] = systemMsg;
msgs[1] = userMsg;

this.completion = new CompletionModel(model, msgs);
}

public CompletionModel getCompletion() {
return completion;
}

public void setCompletion(CompletionModel completion) {
this.completion = completion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,18 @@
* @Copyright 公众号:bugstack虫洞栈 | 博客:https://bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
*/
public class Choices {

private String text;
private Message message;

private int index;

private String logprobs;

private String finish_reason;

public String getText() {
return text;
public Message getMessage() {
return message;
}

public void setText(String text) {
this.text = text;
public void setMessage(Message message) {
this.message = message;
}

public int getIndex() {
Expand All @@ -32,14 +29,6 @@ public void setIndex(int index) {
this.index = index;
}

public String getLogprobs() {
return logprobs;
}

public void setLogprobs(String logprobs) {
this.logprobs = logprobs;
}

public String getFinish_reason() {
return finish_reason;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) Ronnyz. 2023-2023. All rights reserved.
*/

package cn.bugstack.chatbot.api.domain.ai.model.vo;

/**
* OpenAI Completion 请求入参model
*
* @author Ronnyz
* @since 2023/9/30
*/
public class CompletionModel {
/**
* -2.0 和 2.0 之间的数字。正值会根据新标记在文本中的现有频率对其进行惩罚,从而降低模型逐字重复同一行的可能性。
* [查看有关频率和存在惩罚的更多信息。](https://platform.openai.com/docs/api-reference/parameter-details)
*/
private Double frequencyPenalty;
/**
* 修改指定标记出现在完成中的可能性。 接受一个 json 对象,该对象将标记(由标记器中的标记 ID 指定)映射到从 -100 到 100
* 的关联偏差值。从数学上讲,偏差会在采样之前添加到模型生成的 logits 中。确切的效果因模型而异,但 -1 和 1 之间的值应该会减少或增加选择的可能性;像 -100 或
* 100 这样的值应该导致相关令牌的禁止或独占选择。
*/
private Object logitBias;
/**
* 聊天完成时生成的最大令牌数。 输入标记和生成标记的总长度受模型上下文长度的限制。
*/
private Long maxTokens;
/**
* 以[聊天格式](https://platform.openai.com/docs/guides/chat/introduction)生成聊天完成的消息。
*/
private Message[] messages;
/**
* 要使用的模型的 ID。有关哪些模型适用于聊天 API
* 的详细信息,请参阅[模型端点兼容性表。](https://platform.openai.com/docs/models/model-endpoint-compatibility)
*/
private String model;
/**
* 为每个输入消息生成多少个聊天完成选项。
*/
private Long n;
/**
* -2.0 和 2.0 之间的数字。正值会根据到目前为止是否出现在文本中来惩罚新标记,从而增加模型谈论新主题的可能性。
* [查看有关频率和存在惩罚的更多信息。](https://platform.openai.com/docs/api-reference/parameter-details)
*/
private Double presencePenalty;
/**
* API 将停止生成更多令牌的最多 4 个序列。
*/
private String stop;
/**
* 如果设置,将发送部分消息增量,就像在 ChatGPT
* 中一样。当令牌可用时,令牌将作为纯数据[服务器发送事件](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format)`data:
* [DONE]`发送,流由消息终止。[有关示例代码](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb),请参阅
* OpenAI Cookbook 。
*/
private Boolean stream;
/**
* 使用什么采样温度,介于 0 和 2 之间。较高的值(如 0.8)将使输出更加随机,而较低的值(如 0.2)将使输出更加集中和确定。
* 我们通常建议改变这个或`top_p`但不是两者。
*/
private Long temperature;
/**
* 一种替代温度采样的方法,称为核采样,其中模型考虑具有 top_p 概率质量的标记的结果。所以 0.1 意味着只考虑构成前 10% 概率质量的标记。
* 我们通常建议改变这个或`temperature`但不是两者。
*/
private Long topP;
/**
* 代表您的最终用户的唯一标识符,可以帮助 OpenAI
* 监控和检测滥用行为。[了解更多](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids)。
*/
private String user;

public CompletionModel(String model, Message[] messages) {
this.messages = messages;
this.model = model;
}

public Double getFrequencyPenalty() { return frequencyPenalty; }
public void setFrequencyPenalty(Double value) { this.frequencyPenalty = value; }

public Object getLogitBias() { return logitBias; }
public void setLogitBias(Object value) { this.logitBias = value; }

public Long getMaxTokens() { return maxTokens; }
public void setMaxTokens(Long value) { this.maxTokens = value; }

public Message[] getMessages() { return messages; }
public void setMessages(Message[] value) { this.messages = value; }

public String getModel() { return model; }
public void setModel(String value) { this.model = value; }

public Long getN() { return n; }
public void setN(Long value) { this.n = value; }

public Double getPresencePenalty() { return presencePenalty; }
public void setPresencePenalty(Double value) { this.presencePenalty = value; }

public String getStop() { return stop; }
public void setStop(String value) { this.stop = value; }

public Boolean getStream() { return stream; }
public void setStream(Boolean value) { this.stream = value; }

public Long getTemperature() { return temperature; }
public void setTemperature(Long value) { this.temperature = value; }

public Long getTopP() { return topP; }
public void setTopP(Long value) { this.topP = value; }

public String getUser() { return user; }
public void setUser(String value) { this.user = value; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) Ronnyz. 2023-2023. All rights reserved.
*/

package cn.bugstack.chatbot.api.domain.ai.model.vo;

/**
* Message
*
* @author Ronnyz
* @since 2023/9/30
*/
public class Message {
private String content;
private String role;

public Message(String role, String content) {
this.content = content;
this.role = role;
}

public String getContent() { return content; }
public void setContent(String value) { this.content = value; }

public String getRole() { return role; }
public void setRole(String value) { this.role = value; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import cn.bugstack.chatbot.api.domain.ai.IOpenAI;
import cn.bugstack.chatbot.api.domain.ai.model.aggregates.AIAnswer;
import cn.bugstack.chatbot.api.domain.ai.model.aggregates.AIQuestion;
import cn.bugstack.chatbot.api.domain.ai.model.vo.Choices;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpStatus;
Expand All @@ -14,7 +15,6 @@
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
Expand All @@ -31,16 +31,23 @@ public class OpenAI implements IOpenAI {

private Logger logger = LoggerFactory.getLogger(OpenAI.class);

private String proxyUrl = "https://api.openai.com";

private String chatUri = "/v1/chat/completions";

private String model = "gpt-3.5-turbo-0613";

@Override
public String doChatGPT(String openAiKey, String question) throws IOException {

CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 代理地址;open.aiproxy.xyz、open2.aiproxy.xyz
HttpPost post = new HttpPost("https://api.openai.com/v1/completions");
HttpPost post = new HttpPost(proxyUrl + chatUri);
post.addHeader("Content-Type", "application/json");
post.addHeader("Authorization", "Bearer " + openAiKey);

String paramJson = "{\"model\": \"text-davinci-003\", \"prompt\": \"" + question + "\", \"temperature\": 0, \"max_tokens\": 1024}";
AIQuestion aiQuestion = new AIQuestion(model, question);
String paramJson = JSON.toJSONString(aiQuestion.getCompletion());

StringEntity stringEntity = new StringEntity(paramJson, ContentType.create("text/json", "UTF-8"));
post.setEntity(stringEntity);
Expand All @@ -52,7 +59,7 @@ public String doChatGPT(String openAiKey, String question) throws IOException {
StringBuilder answers = new StringBuilder();
List<Choices> choices = aiAnswer.getChoices();
for (Choices choice : choices) {
answers.append(choice.getText());
answers.append(choice.getMessage().getContent());
}
return answers.toString();
} else {
Expand Down
10 changes: 7 additions & 3 deletions chatbot-api-interfaces/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ chatbot-api:
groupId: 28885518425541 # 知识星球ID
cookie: # 知识星球个人cookie信息
openAiKey: # 自行申请 https://beta.openai.com/overview 或者联系小傅哥 fustack 付费申请【购买虚拟号码等需要支付】。
cronExpression: 0/30 * * * * ? # 执行的频次配置,参考:cron.qqe2.com
cronExpression: MC8zMCAqICogKiAqID8= # 0/30 * * * * ? 执行的频次配置,参考:cron.qqe2.com
silenced: false
group02:
groupName: 码农会锁
groupId: 28885518425541 # 知识星球ID
cookie: # 知识星球个人cookie信息
openAiKey: # 自行申请 https://beta.openai.com/overview 或者联系小傅哥 fustack 付费申请【购买虚拟号码等需要支付】。
cronExpression: 0/30 * * * * ? # 执行的频次配置,参考:cron.qqe2.com
silenced: true
cronExpression: MC8zMCAqICogKiAqID8= # 0/30 * * * * ? 执行的频次配置,参考:cron.qqe2.com
silenced: true

logging:
level:
cn.bugstack.chatbot: info
74 changes: 74 additions & 0 deletions chatbot-api-interfaces/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<property name="log.path" value="./logs" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />

<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>

<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 系统模块日志级别控制 -->
<logger name="cn.bugstack.chatbot" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />

<root level="info">
<appender-ref ref="console" />
</root>

<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>
Loading