langchain4j 阿里百炼平台大模型对接

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fyy.config.PersistentChatMemoryStore;
import com.fyy.entity.ApiResponse;
import com.fyy.entity.ChatResponse;
import com.fyy.request.TChatRequest;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@RestController
public class ChatController {

    @Value("${langchain4j.open-ai.chat-model.api-key}")
    private String apiKey;

    @Value("${langchain4j.open-ai.chat-model.model-name}")
    private String modelName;
    // 定义 AI 助手接口
    public interface Assistant {
        String chat(@dev.langchain4j.service.MemoryId int memoryId, @dev.langchain4j.service.UserMessage String userMessage);
    }

    // 构建 ChatMemoryProvider
    private final ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder()
            .id(memoryId)
            .maxMessages(10)
            .chatMemoryStore( new PersistentChatMemoryStore())
            .build();

    // 构建 ChatModel
    private ChatModel createChatModel() {
        return OpenAiChatModel.builder()
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .apiKey(apiKey)
                .modelName(modelName)
                .temperature(0.5)
                .topP(0.9)
                .maxTokens(512)
                .timeout(Duration.ofSeconds(30))
                .logRequests(true)
                .logResponses(true)
                .build();
    }

    @PostMapping("/chat")
    public ApiResponse chat(@RequestBody TChatRequest request) throws JsonProcessingException {
        // Step 1: 创建 ChatModel
        ChatModel model = createChatModel();

        // Step 2: 获取与 memoryId 对应的 ChatMemory
        ChatMemory chatMemory = chatMemoryProvider.get(request.getMemoryId());

        // Step 3: 构建角色设定模板
        String templateString = "你的名字是{{name}},性别是{{gender}},年龄是{{age}}岁。\n" +
                "加上你的开场白介绍,只需要首次聊天介绍一次,每次发消息要有思考的时间,这个时间是随机的2-10s,话多的话自动延迟,你的性格是{{personality}},喜欢{{hobbies}},以第一人称和任何人聊天。只需要用户问你的问题,可以适当拒绝,不用一味讨好用户," +
                "什么动词描述,心里想法,不需要表达,\n" +
                "请用自然、亲切的语气与用户交谈,保持角色设定不变。不需要问想聊些什么的类似问题\n\n" +
                "用户说:{{input}}";
        // 暴躁反派角色模板
//        String templateString = "你的名字是{{name}},性别是{{gender}},年龄是{{age}}岁。\n" +
//                "开场白就是介绍你的身份信息,你的性格是{{personality}},喜欢{{hobbies}}。不用描述肢体语言,以第一人称和任何人聊天,什么动词描述,心里想法,不需要表达\n" +
//                "你是地下黑市的统治者,拥有绝对权威。\n" +
//                "说话时保持威胁性语气,用短促有力的句子,必要时使用暴力威胁。\n" +
//                "对弱者毫不留情,对挑战者充满敌意。\n\n" +
//                "用户说:{{input}}";

        PromptTemplate promptTemplate = PromptTemplate.from(templateString);

        // Step 4: 设置角色参数
        Map<String, Object> variables = new HashMap<>();
        variables.put("name", "小夏");
        variables.put("gender", "");
        variables.put("age", 25);
        variables.put("personality", "开朗、善解人意、有点害羞、没谈过男朋友、好相处、乐于助人");
        variables.put("hobbies", "旅行、摄影、听音乐、打篮球");
        variables.put("input", request.getUserMessage());

//        Map<String, Object> variables = new HashMap<>();
//        variables.put("name", "黑曜");
//        variables.put("gender", "男");
//        variables.put("age", 32);
//        variables.put("personality", "暴躁易怒、心狠手辣、极度自负、睚眦必报、蔑视弱者");
//        variables.put("hobbies", "操控人心、收集武器、摧毁对手、权力斗争");
//        variables.put("input", request.getUserMessage());


        // Step 5: 生成 Prompt 并加入 ChatMemory
        Prompt prompt = promptTemplate.apply(variables);
        chatMemory.add(prompt.toUserMessage());

        // Step 6: 调用模型并获取回复
        AiMessage aiMessage = model.chat(chatMemory.messages()).aiMessage();
        chatMemory.add(aiMessage);  // 将 AI 回复加入记忆

        // Step 8: 返回响应
        return ApiResponse.success(aiMessage.text());
    }
}
package com.fyy.entity;

public class ApiResponse<T> {
    private Integer code;      // 状态码
    private String message;   // 响应消息
    private T data;          // 响应数据,使用泛型
    private Long timestamp;   // 时间戳

    // 构造函数
    public ApiResponse() {
        this.timestamp = System.currentTimeMillis();
    }

    public ApiResponse(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
        this.timestamp = System.currentTimeMillis();
    }

    // 成功响应的静态方法
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "success", data);
    }

    public static <T> ApiResponse<T> success(String message, T data) {
        return new ApiResponse<>(200, message, data);
    }

    // 错误响应的静态方法
    public static <T> ApiResponse<T> error(Integer code, String message) {
        return new ApiResponse<>(code, message, null);
    }

    // getter 和 setter 方法
    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

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

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
    }
}

@Data
public class TChatRequest {
private String userMessage;
private int memoryId;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>AI Chat</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
      background-color: #f0f2f5;
    }
    .chat-container {
      max-width: 800px;
      margin: 0 auto;
      height: 100vh;
      display: flex;
      flex-direction: column;
    }
    .chat-header {
      background-color: #f6f6f6;
      padding: 10px 20px;
      border-bottom: 1px solid #ddd;
    }
    .chat-messages {
      flex: 1;
      overflow-y: auto;
      padding: 20px;
    }
    .message {
      margin-bottom: 20px;
      display: flex;
      flex-direction: column;
    }
    .message.user {
      align-items: flex-end;
    }
    .message.ai {
      align-items: flex-start;
    }
    .message-content {
      max-width: 70%;
      padding: 10px 15px;
      border-radius: 15px;
      margin: 5px 0;
      word-wrap: break-word;
    }
    .user .message-content {
      background-color: #95ec69;
    }
    .ai .message-content {
      background-color: white;
    }
    .chat-input {
      background-color: #f6f6f6;
      padding: 20px;
      border-top: 1px solid #ddd;
    }
    .input-container {
      display: flex;
      gap: 10px;
    }
    textarea {
      flex: 1;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
      resize: none;
      height: 60px;
    }
    button {
      padding: 10px 20px;
      background-color: #07c160;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      height: 82px;
    }
    button:hover {
      background-color: #06ae56;
    }
    button:disabled {
      background-color: #ccc;
    }
    #memoryId {
      width: 60px;
      padding: 5px;
      margin-right: 10px;
    }
  </style>
</head>
<body>
<div class="chat-container">
  <div class="chat-header">
    <h2 style="margin: 0;">AI 聊天室</h2>
    <div style="margin-top: 10px;">
      <label for="memoryId">Memory ID:</label>
      <input type="number" id="memoryId" value="1" min="1" />
    </div>
  </div>

  <div class="chat-messages" id="chatMessages"></div>

  <div class="chat-input">
    <div class="input-container">
                <textarea
                        id="userMessage"
                        placeholder="输入你的问题..."
                        onkeydown="if(event.keyCode === 13 && !event.shiftKey) { event.preventDefault(); sendMessage(); }"
                ></textarea>
      <button onclick="sendMessage()" id="sendButton">发送</button>
    </div>
  </div>
</div>

<script>
  function appendMessage(content, isUser) {
    const messagesDiv = document.getElementById('chatMessages');
    const messageDiv = document.createElement('div');
    messageDiv.className = `message ${isUser ? 'user' : 'ai'}`;

    const contentDiv = document.createElement('div');
    contentDiv.className = 'message-content';
    contentDiv.textContent = content;

    messageDiv.appendChild(contentDiv);
    messagesDiv.appendChild(messageDiv);
    messagesDiv.scrollTop = messagesDiv.scrollHeight;
  }

  function sendMessage() {
    const button = document.getElementById('sendButton');
    const userMessage = document.getElementById('userMessage').value.trim();
    const memoryId = parseInt(document.getElementById('memoryId').value);

    if (!userMessage) {
      alert("请输入消息内容");
      return;
    }

    // 添加用户消息到聊天界面
    appendMessage(userMessage, true);

    // 禁用按钮并显示发送中状态
    button.disabled = true;
    button.textContent = '发送中...';

    const requestPayload = {
      memoryId: memoryId,
      userMessage: userMessage
    };

    fetch('http://localhost:8080/chat', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(requestPayload)
    })
            .then(response => response.json())
            .then(data => {
              console.log('Response:', data);

              if (data.code !== 200) {
                throw new Error(data.message || '请求失败');
              }

              // 添加AI回复到聊天界面
              appendMessage(data.data, false);

              // 清空输入框
              document.getElementById('userMessage').value = '';
            })
            .catch(error => {
              console.error('Error:', error);
              appendMessage(`发生错误: ${error.message}`, false);
            })
            .finally(() => {
              // 恢复按钮状态
              button.disabled = false;
              button.textContent = '发送';
            });
  }
</script>
</body>
</html>
spring.application.name=langchain4j_demo_springboot
#deepseek-v3 qwen-plus qwen-max ??chatglm3-6b  qwen-plus-latest
langchain4j.open-ai.chat-model.api-key=百炼key
langchain4j.open-ai.chat-model.model-name=qwen-plus-latest
langchain4j.open-ai.chat-model.log-requests=true
langchain4j.open-ai.chat-model.log-responses=true
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.fyy</groupId>
    <artifactId>langchain4j_demo_springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>langchain4j_demo_springboot</name>
    <description>langchain4j_demo_springboot</description>
    <properties>
        <java.version>17</java.version>
        <langchain4j.version>1.0.1-beta6</langchain4j.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mapdb</groupId>
            <artifactId>mapdb</artifactId>
            <version>3.0.9</version>
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>org.jetbrains.kotlin</groupId>-->
<!--                    <artifactId>kotlin-stdlib</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-spring-boot-starter</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

<!--    <dependencyManagement>-->
<!--        <dependencies>-->
<!--            <dependency>-->
<!--                <groupId>dev.langchain4j</groupId>-->
<!--                <artifactId>langchain4j-community-bom</artifactId>-->
<!--                <version>${langchain4j.version}</version>-->
<!--                <type>pom</type>-->
<!--                <scope>import</scope>-->
<!--            </dependency>-->
<!--        </dependencies>-->
<!--    </dependencyManagement>-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 



posted @ 2025-05-27 08:37  Fyy发大财  阅读(168)  评论(0)    收藏  举报