Compare commits
6 Commits
Author | SHA1 | Date |
---|---|---|
|
2b72019978 | 4 days ago |
|
33f9bbb055 | 4 days ago |
|
f0337024f1 | 4 days ago |
|
9bfbd3674d | 4 days ago |
|
fab1f9e26c | 5 days ago |
|
1a07e3e4ee | 5 days ago |
@ -0,0 +1,23 @@
|
||||
package xyz.wbsite.achat;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 门户入口
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
@RestController
|
||||
public class HelloController {
|
||||
|
||||
/**
|
||||
* 门户
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public String chat() {
|
||||
return "AChat is running!";
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package xyz.wbsite.achat;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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 xyz.wbsite.achat.core.chat.ChatCompletionRequest;
|
||||
import xyz.wbsite.achat.core.chat.CompletionRequest;
|
||||
import xyz.wbsite.achat.core.chat.CompletionResponse;
|
||||
import xyz.wbsite.achat.core.embed.EmbeddingsRequest;
|
||||
import xyz.wbsite.achat.core.embed.EmbeddingsResponse;
|
||||
import xyz.wbsite.achat.core.model.ModelListResponse;
|
||||
import xyz.wbsite.achat.core.chat.ChatService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* AI会话接口.
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/v1")
|
||||
public class OpenAiController {
|
||||
|
||||
// @Resource
|
||||
// private SessionService sessionService;
|
||||
@Resource
|
||||
private ChatService chatService;
|
||||
|
||||
@RequestMapping()
|
||||
public String info() {
|
||||
return "OpenAI API is support";
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出可用模型
|
||||
* GET /v1/models
|
||||
*/
|
||||
@GetMapping("/models")
|
||||
public ModelListResponse models() {
|
||||
// 实现获取模型列表的逻辑
|
||||
// 这里返回一个示例响应,实际应用中应从服务层获取数据
|
||||
ModelListResponse response = new ModelListResponse();
|
||||
response.setObject("list");
|
||||
// response.setData(/* 实际模型列表 */);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型详情
|
||||
* GET /v1/models/{model}
|
||||
*/
|
||||
@GetMapping("/models/{model}")
|
||||
public Object getModel(@PathVariable String model) {
|
||||
// 实现获取模型详情的逻辑
|
||||
// 这里返回一个示例响应,实际应用中应从服务层获取数据
|
||||
return null; // 替换为实际的模型对象
|
||||
}
|
||||
|
||||
@RequestMapping("/completions")
|
||||
public CompletionResponse completions(@RequestBody CompletionRequest request) {
|
||||
return chatService.prompt(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建聊天完成
|
||||
* POST /v1/chat/completions
|
||||
*/
|
||||
@PostMapping("/chat/completions")
|
||||
public Object createChatCompletion(@RequestBody ChatCompletionRequest request) {
|
||||
if (Boolean.TRUE.equals(request.getStream())) {
|
||||
// 流式响应处理
|
||||
return chatService.streamChat(request);
|
||||
} else {
|
||||
// 非流式响应处理
|
||||
return chatService.chat(request);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/embeddings")
|
||||
public EmbeddingsResponse embeddings(@RequestBody EmbeddingsRequest request) {
|
||||
return chatService.embeddings(request);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package xyz.wbsite.achat;
|
||||
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import xyz.wbsite.achat.core.session.Result;
|
||||
import xyz.wbsite.achat.core.session.Session;
|
||||
import xyz.wbsite.achat.core.session.SessionService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会话服务接口
|
||||
* 提供会话、消息的创建、删除、查询等功能
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
@RestController
|
||||
public class SessionController {
|
||||
|
||||
@Resource
|
||||
private SessionService sessionService;
|
||||
|
||||
/**
|
||||
* 创建会话
|
||||
*
|
||||
* @param uid 用户标识
|
||||
* @return 创建会话响应
|
||||
*/
|
||||
@PostMapping("/{uid}/session")
|
||||
public Result<Session> createSession(@PathVariable("uid") String uid) {
|
||||
return sessionService.createSession(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会话
|
||||
*
|
||||
* @param uid 用户标识
|
||||
* @param sid 会话ID
|
||||
* @return 删除会话响应
|
||||
*/
|
||||
@DeleteMapping("/{uid}/session/{sid}")
|
||||
public Result<Void> deleteSession(@PathVariable("uid") String uid, @PathVariable("sid") String sid) {
|
||||
return sessionService.deleteSession(uid, sid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话详情
|
||||
*
|
||||
* @param uid 用户标识
|
||||
* @param sid 会话ID
|
||||
* @return 删除会话响应
|
||||
*/
|
||||
@GetMapping("/{uid}/session/{sid}")
|
||||
public Result<Session> getSession(@PathVariable("uid") String uid, @PathVariable("sid") String sid) {
|
||||
return sessionService.getSession(uid, sid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话列表
|
||||
*
|
||||
* @param uid 用户标识
|
||||
* @return 会话列表响应
|
||||
*/
|
||||
@GetMapping("/{uid}/session/list")
|
||||
public Result<List<Session>> listSession(@PathVariable("uid") String uid) {
|
||||
return sessionService.listSessions(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会话历史消息
|
||||
*
|
||||
* @param uid 用户标识
|
||||
* @param sid 会话ID
|
||||
* @return 删除会话响应
|
||||
*/
|
||||
@DeleteMapping("/{uid}/session/{sid}/messages/{mid}")
|
||||
public Result<Void> deleteMessage(@PathVariable("uid") String uid, @PathVariable("sid") String sid, @PathVariable("mid") String mid) {
|
||||
return sessionService.deleteMessage(uid, sid, mid);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package xyz.wbsite.achat.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import xyz.wbsite.achat.core.chat.ChatService;
|
||||
import xyz.wbsite.achat.core.chat.ChatServiceSampleImpl;
|
||||
import xyz.wbsite.achat.core.session.SessionService;
|
||||
import xyz.wbsite.achat.core.session.SessionServiceMemoryImpl;
|
||||
|
||||
/**
|
||||
* 对话配置
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
@Configuration
|
||||
public class ChatConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public ChatService chatService() {
|
||||
return new ChatServiceSampleImpl();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SessionService sessionService() {
|
||||
return new SessionServiceMemoryImpl();
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package xyz.wbsite.achat.core.base;
|
||||
|
||||
/**
|
||||
* 附件
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class Attachment {
|
||||
private String filename;
|
||||
|
||||
private String fid;
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public String getFid() {
|
||||
return fid;
|
||||
}
|
||||
|
||||
public void setFid(String fid) {
|
||||
this.fid = fid;
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package xyz.wbsite.achat.core.base;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 服务器推送事件
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class Event {
|
||||
|
||||
private String sid;
|
||||
|
||||
private Date time;
|
||||
|
||||
private String text;
|
||||
|
||||
private String type;
|
||||
|
||||
public Event(String sid) {
|
||||
this.sid = sid;
|
||||
this.time = new Date();
|
||||
}
|
||||
|
||||
public String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void setSid(String sid) {
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
public Date getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Date time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package xyz.wbsite.achat.core.base;
|
||||
|
||||
import xyz.wbsite.achat.enums.Role;
|
||||
|
||||
/**
|
||||
* 消息
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class Message {
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
private Role role;
|
||||
|
||||
/**
|
||||
* 会话ID
|
||||
*/
|
||||
private String sid;
|
||||
|
||||
/**
|
||||
* 消息
|
||||
*/
|
||||
private String content;
|
||||
|
||||
public Role getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(Role role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void setSid(String sid) {
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package xyz.wbsite.achat.core.base;
|
||||
|
||||
public class Prompt {
|
||||
|
||||
/**
|
||||
* 提示词
|
||||
*/
|
||||
private String prompt;
|
||||
|
||||
public String getPrompt() {
|
||||
return prompt;
|
||||
}
|
||||
|
||||
public void setPrompt(String prompt) {
|
||||
this.prompt = prompt;
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package xyz.wbsite.achat.core.chat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OpenAI聊天完成请求 - 符合OpenAI官方API规范
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class ChatCompletionRequest {
|
||||
private String model;
|
||||
private List<Message> messages;
|
||||
private Double temperature;
|
||||
private Double top_p;
|
||||
private Integer n;
|
||||
private Boolean stream;
|
||||
private List<String> stop;
|
||||
private Integer max_tokens;
|
||||
private Double presence_penalty;
|
||||
private Double frequency_penalty;
|
||||
private Object logit_bias;
|
||||
private String user;
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public List<Message> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public void setMessages(List<Message> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
public Double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setTemperature(Double temperature) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
public Double getTop_p() {
|
||||
return top_p;
|
||||
}
|
||||
|
||||
public void setTop_p(Double top_p) {
|
||||
this.top_p = top_p;
|
||||
}
|
||||
|
||||
public Integer getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
public void setN(Integer n) {
|
||||
this.n = n;
|
||||
}
|
||||
|
||||
public Boolean getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(Boolean stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public List<String> getStop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
public void setStop(List<String> stop) {
|
||||
this.stop = stop;
|
||||
}
|
||||
|
||||
public Integer getMax_tokens() {
|
||||
return max_tokens;
|
||||
}
|
||||
|
||||
public void setMax_tokens(Integer max_tokens) {
|
||||
this.max_tokens = max_tokens;
|
||||
}
|
||||
|
||||
public Double getPresence_penalty() {
|
||||
return presence_penalty;
|
||||
}
|
||||
|
||||
public void setPresence_penalty(Double presence_penalty) {
|
||||
this.presence_penalty = presence_penalty;
|
||||
}
|
||||
|
||||
public Double getFrequency_penalty() {
|
||||
return frequency_penalty;
|
||||
}
|
||||
|
||||
public void setFrequency_penalty(Double frequency_penalty) {
|
||||
this.frequency_penalty = frequency_penalty;
|
||||
}
|
||||
|
||||
public Object getLogit_bias() {
|
||||
return logit_bias;
|
||||
}
|
||||
|
||||
public void setLogit_bias(Object logit_bias) {
|
||||
this.logit_bias = logit_bias;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package xyz.wbsite.achat.core.chat;
|
||||
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
import xyz.wbsite.achat.core.embed.EmbeddingsRequest;
|
||||
import xyz.wbsite.achat.core.embed.EmbeddingsResponse;
|
||||
|
||||
public interface ChatService {
|
||||
|
||||
CompletionResponse prompt(CompletionRequest request);
|
||||
|
||||
ChatCompletionResponse chat(ChatCompletionRequest request);
|
||||
|
||||
SseEmitter streamChat(ChatCompletionRequest request);
|
||||
|
||||
EmbeddingsResponse embeddings(EmbeddingsRequest request);
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package xyz.wbsite.achat.core.chat;
|
||||
|
||||
/**
|
||||
* 文本补全请求
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class CompletionRequest {
|
||||
private String model;
|
||||
private String prompt;
|
||||
private boolean stream;
|
||||
|
||||
private Double temperature;
|
||||
private Integer max_tokens;
|
||||
private Double top_p;
|
||||
private Integer n;
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getPrompt() {
|
||||
return prompt;
|
||||
}
|
||||
|
||||
public void setPrompt(String prompt) {
|
||||
this.prompt = prompt;
|
||||
}
|
||||
|
||||
public Integer getMax_tokens() {
|
||||
return max_tokens;
|
||||
}
|
||||
|
||||
public void setMax_tokens(Integer max_tokens) {
|
||||
this.max_tokens = max_tokens;
|
||||
}
|
||||
|
||||
public Double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setTemperature(Double temperature) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
public Double getTop_p() {
|
||||
return top_p;
|
||||
}
|
||||
|
||||
public void setTop_p(Double top_p) {
|
||||
this.top_p = top_p;
|
||||
}
|
||||
|
||||
public Integer getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
public void setN(Integer n) {
|
||||
this.n = n;
|
||||
}
|
||||
}
|
@ -0,0 +1,204 @@
|
||||
package xyz.wbsite.achat.core.chat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OpenAI聊天完成响应 - 符合OpenAI官方API规范
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class CompletionResponse {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String model;
|
||||
private List<Choice> choices;
|
||||
private Usage usage;
|
||||
|
||||
private CompletionResponse(Builder builder) {
|
||||
this.id = builder.id;
|
||||
this.object = builder.object;
|
||||
this.created = builder.created;
|
||||
this.model = builder.model;
|
||||
this.choices = builder.choices;
|
||||
this.usage = builder.usage;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
public void setObject(String object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public long getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(long created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public List<Choice> getChoices() {
|
||||
return choices;
|
||||
}
|
||||
|
||||
public void setChoices(List<Choice> choices) {
|
||||
this.choices = choices;
|
||||
}
|
||||
|
||||
public Usage getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public void setUsage(Usage usage) {
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String model;
|
||||
private List<Choice> choices = new ArrayList<>();
|
||||
private Usage usage;
|
||||
|
||||
public Builder id(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder object(String object) {
|
||||
this.object = object;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder created(long created) {
|
||||
this.created = created;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder model(String model) {
|
||||
this.model = model;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder choices(List<Choice> choices) {
|
||||
this.choices = choices;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withChoices(java.util.function.Consumer<List<Choice>> choicesConsumer) {
|
||||
choicesConsumer.accept(this.choices);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder usage(Usage usage) {
|
||||
this.usage = usage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CompletionResponse build() {
|
||||
return new CompletionResponse(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Choice {
|
||||
private int index = 0;
|
||||
private Message message;
|
||||
private String finish_reason;
|
||||
|
||||
public Integer getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(Integer index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Message getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(Message message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getFinish_reason() {
|
||||
return finish_reason;
|
||||
}
|
||||
|
||||
public void setFinish_reason(String finish_reason) {
|
||||
this.finish_reason = finish_reason;
|
||||
}
|
||||
}
|
||||
|
||||
public static ChoiceBuilder choiceBuilder() {
|
||||
return new ChoiceBuilder();
|
||||
}
|
||||
|
||||
public static class ChoiceBuilder {
|
||||
private Integer index;
|
||||
private Role role;
|
||||
private String content;
|
||||
private String name;
|
||||
private String finish_reason;
|
||||
|
||||
public ChoiceBuilder index(Integer index) {
|
||||
this.index = index;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChoiceBuilder role(Role role) {
|
||||
this.role = role;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChoiceBuilder content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChoiceBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChoiceBuilder finish_reason(String finish_reason) {
|
||||
this.finish_reason = finish_reason;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Choice build() {
|
||||
Choice choice = new Choice();
|
||||
choice.setIndex(index);
|
||||
choice.setMessage(Message.builder().role(role).content(content).name(name).build());
|
||||
choice.setFinish_reason(finish_reason);
|
||||
return choice;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package xyz.wbsite.achat.enums;
|
||||
package xyz.wbsite.achat.core.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package xyz.wbsite.achat.enums;
|
||||
package xyz.wbsite.achat.core.chat;
|
||||
|
||||
/**
|
||||
* 消息状态枚举
|
@ -0,0 +1,88 @@
|
||||
package xyz.wbsite.achat.core.chat;
|
||||
|
||||
/**
|
||||
* 令牌使用统计
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class Usage {
|
||||
|
||||
/**
|
||||
* 提示词 tokens 数量
|
||||
*/
|
||||
private int prompt_tokens;
|
||||
|
||||
/**
|
||||
* 补全 tokens 数量
|
||||
*/
|
||||
private int completion_tokens;
|
||||
|
||||
/**
|
||||
* 总 tokens 数量
|
||||
*/
|
||||
private int total_tokens;
|
||||
|
||||
public Usage() {
|
||||
}
|
||||
|
||||
private Usage(Builder builder) {
|
||||
this.prompt_tokens = builder.prompt_tokens;
|
||||
this.completion_tokens = builder.completion_tokens;
|
||||
this.total_tokens = builder.total_tokens;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public int getPrompt_tokens() {
|
||||
return prompt_tokens;
|
||||
}
|
||||
|
||||
public void setPrompt_tokens(int prompt_tokens) {
|
||||
this.prompt_tokens = prompt_tokens;
|
||||
}
|
||||
|
||||
public int getCompletion_tokens() {
|
||||
return completion_tokens;
|
||||
}
|
||||
|
||||
public void setCompletion_tokens(int completion_tokens) {
|
||||
this.completion_tokens = completion_tokens;
|
||||
}
|
||||
|
||||
public int getTotal_tokens() {
|
||||
return total_tokens;
|
||||
}
|
||||
|
||||
public void setTotal_tokens(int total_tokens) {
|
||||
this.total_tokens = total_tokens;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private int prompt_tokens;
|
||||
private int completion_tokens;
|
||||
private int total_tokens;
|
||||
|
||||
public Builder prompt_tokens(int prompt_tokens) {
|
||||
this.prompt_tokens = prompt_tokens;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder completion_tokens(int completion_tokens) {
|
||||
this.completion_tokens = completion_tokens;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder total_tokens(int total_tokens) {
|
||||
this.total_tokens = total_tokens;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Usage build() {
|
||||
return new Usage(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package xyz.wbsite.achat.core.embed;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 嵌入请求 - 符合OpenAI官方API规范
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class EmbeddingsRequest {
|
||||
private String model;
|
||||
private List<String> input;
|
||||
private String user;
|
||||
|
||||
public EmbeddingsRequest() {
|
||||
}
|
||||
|
||||
private EmbeddingsRequest(Builder builder) {
|
||||
this.model = builder.model;
|
||||
this.input = builder.input;
|
||||
this.user = builder.user;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public List<String> getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public void setInput(List<String> input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(String user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String model;
|
||||
private List<String> input = new ArrayList<>();
|
||||
private String user;
|
||||
|
||||
public Builder model(String model) {
|
||||
this.model = model;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder input(List<String> input) {
|
||||
this.input = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addInput(String text) {
|
||||
this.input.add(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder user(String user) {
|
||||
this.user = user;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmbeddingsRequest build() {
|
||||
return new EmbeddingsRequest(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package xyz.wbsite.achat.core.event;
|
||||
|
||||
import xyz.wbsite.achat.core.base.Event;
|
||||
|
||||
/**
|
||||
* 完成事件
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class CompleteEvent extends Event {
|
||||
|
||||
public CompleteEvent(String sid) {
|
||||
super(sid);
|
||||
setType("complete");
|
||||
}
|
||||
|
||||
public static CompleteEvent of(String sid) {
|
||||
return new CompleteEvent(sid);
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package xyz.wbsite.achat.core.event;
|
||||
|
||||
import xyz.wbsite.achat.core.base.Event;
|
||||
|
||||
/**
|
||||
* 部分消息事件
|
||||
* <p>
|
||||
* 用于流式会话下表示AI回复的部分消息
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class PartialEvent extends Event {
|
||||
public PartialEvent(String sid) {
|
||||
super(sid);
|
||||
setType("partial");
|
||||
}
|
||||
|
||||
public PartialEvent(String sid, String partial) {
|
||||
super(sid);
|
||||
setType("partial");
|
||||
setText(partial);
|
||||
}
|
||||
|
||||
public static PartialEvent of(String sid, String partial) {
|
||||
return new PartialEvent(sid, partial);
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package xyz.wbsite.achat.core.message;
|
||||
|
||||
|
||||
import xyz.wbsite.achat.core.base.Message;
|
||||
|
||||
/**
|
||||
* 用户消息
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class AiMessage extends Message {
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package xyz.wbsite.achat.core.message;
|
||||
|
||||
import xyz.wbsite.achat.core.base.Attachment;
|
||||
import xyz.wbsite.achat.core.base.Message;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户消息
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class UserMessage extends Message {
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private String uid;
|
||||
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
private List<Attachment> attachments;
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public List<Attachment> getAttachments() {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public void setAttachments(List<Attachment> attachments) {
|
||||
this.attachments = attachments;
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package xyz.wbsite.achat.core.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OpenAI模型对象 - 符合OpenAI官方API规范
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class Model {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private String owned_by;
|
||||
private List<Permission> permission;
|
||||
private String root;
|
||||
private String parent;
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
public String getObject() { return object; }
|
||||
public void setObject(String object) { this.object = object; }
|
||||
public long getCreated() { return created; }
|
||||
public void setCreated(long created) { this.created = created; }
|
||||
public String getOwned_by() { return owned_by; }
|
||||
public void setOwned_by(String owned_by) { this.owned_by = owned_by; }
|
||||
public List<Permission> getPermission() { return permission; }
|
||||
public void setPermission(List<Permission> permission) { this.permission = permission; }
|
||||
public String getRoot() { return root; }
|
||||
public void setRoot(String root) { this.root = root; }
|
||||
public String getParent() { return parent; }
|
||||
public void setParent(String parent) { this.parent = parent; }
|
||||
|
||||
/**
|
||||
* 模型权限对象
|
||||
*/
|
||||
public static class Permission {
|
||||
private String id;
|
||||
private String object;
|
||||
private long created;
|
||||
private boolean allow_create_engine;
|
||||
private boolean allow_sampling;
|
||||
private boolean allow_logprobs;
|
||||
private boolean allow_search_indices;
|
||||
private boolean allow_view;
|
||||
private boolean allow_fine_tuning;
|
||||
private String organization;
|
||||
private String group;
|
||||
private boolean is_blocking;
|
||||
|
||||
// Getters and Setters
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
public String getObject() { return object; }
|
||||
public void setObject(String object) { this.object = object; }
|
||||
public long getCreated() { return created; }
|
||||
public void setCreated(long created) { this.created = created; }
|
||||
public boolean isAllow_create_engine() { return allow_create_engine; }
|
||||
public void setAllow_create_engine(boolean allow_create_engine) { this.allow_create_engine = allow_create_engine; }
|
||||
public boolean isAllow_sampling() { return allow_sampling; }
|
||||
public void setAllow_sampling(boolean allow_sampling) { this.allow_sampling = allow_sampling; }
|
||||
public boolean isAllow_logprobs() { return allow_logprobs; }
|
||||
public void setAllow_logprobs(boolean allow_logprobs) { this.allow_logprobs = allow_logprobs; }
|
||||
public boolean isAllow_search_indices() { return allow_search_indices; }
|
||||
public void setAllow_search_indices(boolean allow_search_indices) { this.allow_search_indices = allow_search_indices; }
|
||||
public boolean isAllow_view() { return allow_view; }
|
||||
public void setAllow_view(boolean allow_view) { this.allow_view = allow_view; }
|
||||
public boolean isAllow_fine_tuning() { return allow_fine_tuning; }
|
||||
public void setAllow_fine_tuning(boolean allow_fine_tuning) { this.allow_fine_tuning = allow_fine_tuning; }
|
||||
public String getOrganization() { return organization; }
|
||||
public void setOrganization(String organization) { this.organization = organization; }
|
||||
public String getGroup() { return group; }
|
||||
public void setGroup(String group) { this.group = group; }
|
||||
public boolean isIs_blocking() { return is_blocking; }
|
||||
public void setIs_blocking(boolean is_blocking) { this.is_blocking = is_blocking; }
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package xyz.wbsite.achat.core.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OpenAI模型列表响应 - 符合OpenAI官方API规范
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class ModelListResponse {
|
||||
private String object;
|
||||
private List<Model> data;
|
||||
|
||||
// Getters and Setters
|
||||
public String getObject() { return object; }
|
||||
public void setObject(String object) { this.object = object; }
|
||||
public List<Model> getData() { return data; }
|
||||
public void setData(List<Model> data) { this.data = data; }
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package xyz.wbsite.achat.core.prompt;
|
||||
|
||||
import xyz.wbsite.achat.core.base.Message;
|
||||
import xyz.wbsite.achat.core.base.Prompt;
|
||||
import xyz.wbsite.achat.core.message.UserMessage;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MessagePrompt extends Prompt {
|
||||
|
||||
/**
|
||||
* 模型
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 消息列表
|
||||
*/
|
||||
private List<Message> messages;
|
||||
|
||||
/**
|
||||
* 是否流式返回
|
||||
*/
|
||||
private Boolean stream;
|
||||
|
||||
/**
|
||||
* 最大token数
|
||||
*/
|
||||
private Integer maxTokens;
|
||||
|
||||
/**
|
||||
* 温度参
|
||||
*/
|
||||
private Double temperature;
|
||||
|
||||
/**
|
||||
* 额外参数
|
||||
*/
|
||||
private Map<String, Object> extraParams;
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public List<Message> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public void setMessages(List<Message> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
public Boolean getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(Boolean stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public Integer getMaxTokens() {
|
||||
return maxTokens;
|
||||
}
|
||||
|
||||
public void setMaxTokens(Integer maxTokens) {
|
||||
this.maxTokens = maxTokens;
|
||||
}
|
||||
|
||||
public Double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setTemperature(Double temperature) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
public Map<String, Object> getExtraParams() {
|
||||
return extraParams;
|
||||
}
|
||||
|
||||
public void setExtraParams(Map<String, Object> extraParams) {
|
||||
this.extraParams = extraParams;
|
||||
}
|
||||
|
||||
|
||||
public UserMessage getLastUserMessage() {
|
||||
List<Message> messageList = messages.stream().filter(message -> message instanceof UserMessage).collect(Collectors.toList());
|
||||
UserMessage userMessage = (UserMessage)messageList.get(messageList.size() - 1);
|
||||
return userMessage;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return getLastUserMessage().getUid();
|
||||
}
|
||||
|
||||
public String getSid(){
|
||||
return getLastUserMessage().getSid();
|
||||
}
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package xyz.wbsite.achat.core.service;
|
||||
|
||||
import xyz.wbsite.achat.core.message.MessageSseEmitter;
|
||||
import xyz.wbsite.achat.core.base.Message;
|
||||
|
||||
/**
|
||||
* 消息生成器
|
||||
* <p>
|
||||
* 抽象出来用于生成消息的实现层
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface MessageGenerator {
|
||||
|
||||
void on(MessageSseEmitter emitter, Message message);
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package xyz.wbsite.achat.core.service.impl;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
import xyz.wbsite.achat.core.message.MessageSseEmitter;
|
||||
import xyz.wbsite.achat.core.base.Message;
|
||||
import xyz.wbsite.achat.core.base.Result;
|
||||
import xyz.wbsite.achat.core.base.Session;
|
||||
import xyz.wbsite.achat.core.message.UserMessage;
|
||||
import xyz.wbsite.achat.core.prompt.MessagePrompt;
|
||||
import xyz.wbsite.achat.core.service.SessionService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 会话管理服务实现类
|
||||
* 实现会话的创建、删除、查询、消息收发等功能
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
@Service
|
||||
public class SessionServiceMemoryImpl implements SessionService {
|
||||
|
||||
private final Map<String, Session> sessionStore = new HashMap<>();
|
||||
|
||||
private final List<Message> messageStore = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
*/
|
||||
@Override
|
||||
public Result<Session> createSession(String uid) {
|
||||
Session session = new Session();
|
||||
session.setId(String.valueOf(UUID.randomUUID().toString()));
|
||||
session.setUid(uid);
|
||||
session.setTitle("新对话");
|
||||
sessionStore.put(session.getId(), session);
|
||||
return Result.success(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会话
|
||||
*/
|
||||
@Override
|
||||
public Result<Void> deleteSession(String sid) {
|
||||
sessionStore.remove(sid);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询会话列表
|
||||
*/
|
||||
@Override
|
||||
public Result<List<Session>> listSessions(String uid) {
|
||||
List<Session> collect = sessionStore.values()
|
||||
.stream()
|
||||
.filter(item -> item.getUid().equals(uid))
|
||||
.collect(Collectors.toList());
|
||||
return Result.success(collect);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话详情
|
||||
*/
|
||||
@Override
|
||||
public Result<Session> getSession(String sid) {
|
||||
Session session = sessionStore.get(sid);
|
||||
if (session == null) {
|
||||
return Result.error("会话不存在");
|
||||
}
|
||||
return Result.success(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息并获取流式响应
|
||||
*/
|
||||
@Override
|
||||
public SseEmitter sendMessage(MessagePrompt message) {
|
||||
// 创建VChatSseEmitter来处理流式响应
|
||||
return new MessageSseEmitter(message, (emitter, message1) -> {
|
||||
// 这边模拟LLM复述一遍用户问题
|
||||
String text = message1.getContent();
|
||||
for (char c : text.toCharArray()) {
|
||||
if (emitter.isComplete()) {
|
||||
return;
|
||||
}
|
||||
emitter.onPartialResponse(String.valueOf(c));
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
emitter.onCompleteResponse(null);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Void> stopSession(String sid) {
|
||||
// todo
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<List<Message>> listMessage(String sid) {
|
||||
List<Message> messages = messageStore.stream().filter(item -> item.getSid().equals(sid)).collect(Collectors.toList());
|
||||
return Result.success(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Void> deleteMessage(String sid) {
|
||||
messageStore.forEach(item -> messageStore.remove(item));
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package xyz.wbsite.achat.core.session;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Message extends xyz.wbsite.achat.core.chat.Message {
|
||||
private String id;
|
||||
private String uid;
|
||||
private String sid;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void setSid(String sid) {
|
||||
this.sid = sid;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package xyz.wbsite.achat.core.session;
|
||||
|
||||
import xyz.wbsite.achat.core.chat.Message;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会话管理服务接口
|
||||
* 提供会话的创建、删除、查询、消息收发等功能
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface SessionService {
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
*
|
||||
* @param uid 用户编号
|
||||
* @return 创建的会话对象
|
||||
*/
|
||||
Result<Session> createSession(String uid);
|
||||
|
||||
/**
|
||||
* 删除会话
|
||||
*
|
||||
* @param sid 会话ID
|
||||
* @return 删除是否成功
|
||||
*/
|
||||
Result<Void> deleteSession(String uid, String sid);
|
||||
|
||||
/**
|
||||
* 查询会话列表
|
||||
*
|
||||
* @param uid 用户编号
|
||||
* @return 会话列表
|
||||
*/
|
||||
Result<List<Session>> listSessions(String uid);
|
||||
|
||||
/**
|
||||
* 获取会话详情
|
||||
*
|
||||
* @param sid 会话ID
|
||||
* @return 会话对象
|
||||
*/
|
||||
Result<Session> getSession(String uid,String sid);
|
||||
|
||||
/**
|
||||
* 获取会话历史消息
|
||||
*
|
||||
* @param sid 会话ID
|
||||
* @return 消息列表
|
||||
*/
|
||||
Result<Void> deleteMessage(String uid, String sid, String mid);
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package xyz.wbsite.achat.core.session;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 会话管理服务实现类
|
||||
* 实现会话的创建、删除、查询、消息收发等功能
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 1.8
|
||||
*/
|
||||
public class SessionServiceMemoryImpl implements SessionService {
|
||||
|
||||
/**
|
||||
* 会话存储
|
||||
*/
|
||||
private final List<Session> sessionStore = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 消息存储
|
||||
*/
|
||||
private final List<Message> messageStore = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 创建新会话
|
||||
*
|
||||
* @param uid 用户ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Result<Session> createSession(String uid) {
|
||||
// 检查参数合法性
|
||||
if (uid == null || uid.isEmpty()) {
|
||||
return Result.error("用户ID不能为空");
|
||||
}
|
||||
|
||||
Session session = new Session();
|
||||
session.setId(String.valueOf(UUID.randomUUID().toString()));
|
||||
session.setUid(uid);
|
||||
session.setTitle("新对话");
|
||||
sessionStore.add(session);
|
||||
return Result.success(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会话
|
||||
*
|
||||
* @param uid 用户ID
|
||||
* @param sid 会话ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Result<Void> deleteSession(String uid, String sid) {
|
||||
// 检查参数合法性
|
||||
if (uid == null || uid.isEmpty() || sid == null || sid.isEmpty()) {
|
||||
return Result.error("用户ID或会话ID不能为空");
|
||||
}
|
||||
|
||||
// 从sessionStore查找比对uid和sid然后删除
|
||||
boolean sessionRemoved = sessionStore.removeIf(session ->
|
||||
session.getId().equals(sid) && session.getUid().equals(uid)
|
||||
);
|
||||
|
||||
// 从messageStore查找比对uid和sid然后删除
|
||||
messageStore.removeIf(message ->
|
||||
message.getUid().equals(uid) && message.getSid().equals(sid)
|
||||
);
|
||||
|
||||
if (!sessionRemoved) {
|
||||
return Result.error("会话不存在或无权限删除");
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询会话列表
|
||||
*
|
||||
* @param uid 用户ID
|
||||
* @return
|
||||
*/
|
||||
/**
|
||||
* 查询会话列表
|
||||
*
|
||||
* @param uid 用户ID
|
||||
* @return 会话列表
|
||||
*/
|
||||
@Override
|
||||
public Result<List<Session>> listSessions(String uid) {
|
||||
// 检查参数合法性
|
||||
if (uid == null || uid.isEmpty()) {
|
||||
return Result.error("用户ID不能为空");
|
||||
}
|
||||
|
||||
// 从sessionStore查找比对uid返回所有会话
|
||||
List<Session> userSessions = sessionStore.stream()
|
||||
.filter(session -> session.getUid().equals(uid))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Result.success(userSessions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话详情
|
||||
*
|
||||
* @param uid 用户ID
|
||||
* @param sid 会话ID
|
||||
* @return 会话详情
|
||||
*/
|
||||
@Override
|
||||
public Result<Session> getSession(String uid, String sid) {
|
||||
// 检查参数合法性
|
||||
if (uid == null || uid.isEmpty() || sid == null || sid.isEmpty()) {
|
||||
return Result.error("用户ID或会话ID不能为空");
|
||||
}
|
||||
|
||||
// 从sessionStore查找比对uid和sid返回会话
|
||||
Session session = sessionStore.stream()
|
||||
.filter(s -> s.getId().equals(sid) && s.getUid().equals(uid))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (session == null) {
|
||||
return Result.error("会话不存在或无权限查看");
|
||||
}
|
||||
|
||||
// 创建会话副本
|
||||
Session sessionCopy = new Session();
|
||||
sessionCopy.setId(session.getId());
|
||||
sessionCopy.setUid(session.getUid());
|
||||
sessionCopy.setTitle(session.getTitle());
|
||||
|
||||
// 从messageStore检索出当前会话的聊天记录
|
||||
List<Message> sessionMessages = messageStore.stream()
|
||||
.filter(message -> message.getUid().equals(uid) && message.getSid().equals(sid))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
sessionCopy.setMessages(sessionMessages);
|
||||
|
||||
return Result.success(sessionCopy);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会话中的消息
|
||||
*
|
||||
* @param uid 用户ID
|
||||
* @param sid 会话ID
|
||||
* @param mid 消息ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Result<Void> deleteMessage(String uid, String sid, String mid) {
|
||||
// 检查参数合法性
|
||||
if (uid == null || uid.isEmpty() || sid == null || sid.isEmpty() || mid == null || mid.isEmpty()) {
|
||||
return Result.error("用户ID、会话ID或消息ID不能为空");
|
||||
}
|
||||
|
||||
// 从messageStore查找比对uid、sid和mid然后删除
|
||||
boolean mr = messageStore.removeIf(message ->
|
||||
message.getId().equals(mid) && message.getUid().equals(uid) && message.getSid().equals(sid)
|
||||
);
|
||||
|
||||
if (!mr) {
|
||||
return Result.error("消息不存在或无权限删除");
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
}
|
Loading…
Reference in new issue