RAG中动态上下文管理学习记录

动态上下文管理学习记录

1.1 滑动窗口法(Sliding Window)

保留最近的N条消息作为上下文,丢弃较早的消息。这种方法在聊天应用中常见,例如OpenAI的ChatGPT会限制历史消息数量。

滑动窗口管理器:

csharp 复制代码
public class ConversationManager {
    private int maxHistory;
    private List<String> history;
​
    /**
     * 初始化对话管理器,设置最大历史消息数。
     * @param maxHistory 最大保留的消息数
     */
    public ConversationManager(int maxHistory) {
        this.maxHistory = maxHistory;
        this.history = new ArrayList<>();
    }
​
    /**
     * 添加新消息,超出最大历史时移除最早消息。
     * @param message 新消息
     */
    public void addMessage(String message) {
        history.add(message);
        if (history.size() > maxHistory) {
            history.remove(0);
        }
    }
​
    /**
     * 获取当前历史消息。
     * @return 历史消息列表
     */
    public List<String> getHistory() {
        return new ArrayList<>(history);
    }
}

使用思路:首先是在系统提示词中要留出滑动窗口历史信息的占位,然后在每次提问前判断并获取历史信息,最后在每一轮得到模型回答后将问答保存进管理器中,所以这也要求管理器的大小得是偶数。具体测试最后统一给出。

1.2 关键词提取法(Keyword Extraction)

1.2.1 技术原理

从对话中提取关键信息(如人名、地点、日期等),存储为键值对,并在生成提示时加入这些信息。这种方法通过只保留必要信息来节省令牌。

1.2.2 方法优缺点

  • 优点:高效,专注于关键事实,减少冗余
  • 缺点:依赖实体提取的准确性,可能遗漏非结构化信息

1.2.3 适用场景

需要长期记忆用户信息的对话系统(如客服机器人)

1.2.4 实现技术

可使用命名实体识别(NER)模型,如Stanford CoreNLP或通过API调用(如OpenAI)提取实体。

同样,也有一个上下文管理器:

typescript 复制代码
public class KeyInformationManager {
    private Map<String, String> entities = new HashMap<>();
​
    /**
     * 更新存储的实体。
     * @param newEntities 新提取的实体
     */
    public void updateEntities(Map<String, String> newEntities) {
        entities.putAll(newEntities);
    }
​
    /**
     * 获取当前上下文(所有实体)。
     * @return 上下文字符串
     */
    public String getContext() {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : entities.entrySet()) {
            sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
        }
        return sb.toString();
    }
}
​

关键词提取还需要配合关键词提取器,定义如下:

typescript 复制代码
public interface EntityExtractor {
    /**
     * 从消息中提取实体。
     * @param message 输入消息
     * @return 实体键值对
     */
    Map<String, String> extractEntities(String message);
}
​
typescript 复制代码
@Slf4j
@Component // Make this class a Spring Bean
public class LlmEntityExtractor implements EntityExtractor{
​
    @Resource
    private OllamaChatClient ollamaChatClient;
​
    // System Prompt specifically designed for JSON output
    private static final String SYSTEM_PROMPT = """
            你是文本实体提取助手。
            你的任务是从用户提供的文本中提取关键实体、术语或概念。
            将提取的实体组织成一个 JSON 对象返回。
            
            重要提示:你的回复必须严格遵守以下格式要求:
            1.  你的回复必须是一个有效的 JSON 对象,例如 {"key1": "value1", "key2": "value2"}。
            2.  JSON 对象的键应该是描述性的实体类型(如 'topic', 'location', 'person', 'organization', 'term')或通用标签(如 'term1', 'term2'),值是提取到的实体文本。
            3.  只输出这个 JSON 对象本身。
            4.  绝对不要在 JSON 对象之前或之后添加任何文本、解释、问候语、代码块标记(```json ... ```)或任何其他字符。
            5.  你的整个回复必须是一个格式良好的 JSON 字符串,可以直接被解析。
            
            示例输入:"我想了解 Spring AI 和 Ollama 的集成。"
            示例输出:{"topic": "Spring AI", "tool": "Ollama", "action": "integration"}
            """;
​
    @Override
    public Map<String, String> extractEntities(String message) {
        if (message == null || message.trim().isEmpty()) {
            log.warn("输入消息为空,无法提取实体。");
            return Collections.emptyMap(); // Return empty map for empty input
        }
​
        // 1. Create System and User Messages
        SystemMessage systemMessage = new SystemMessage(SYSTEM_PROMPT);
        UserMessage userMessage = new UserMessage("请从以下文本中提取实体:\n\n" + message);
​
        // 2. Combine into Prompt
        List<Message> promptMessages = new ArrayList<>();
        promptMessages.add(systemMessage);
        promptMessages.add(userMessage);
​
        // 3. Call LLM
        log.info("调用 Ollama 模型进行实体提取...");
        try {
            // Use a model suitable for instruction following and JSON generation
            // Adjust model name if needed
            ChatResponse chatResponse = ollamaChatClient.call(new Prompt(promptMessages, OllamaOptions.create().withModel("deepseek-r1:1.5b")));
​
            String rawContent = chatResponse.getResult().getOutput().getContent();
            log.info("LLM 返回的原始完整内容: [{}]", rawContent);
​
            // 使用 LlmResponseUtils 辅助方法提取可能存在的 think 块之后的内容
            String jsonResponseString = LlmResponseUtils.extractContentAfterThinkBlock(rawContent);
            log.info("处理 think 块后用于 JSON 解析的字符串: [{}]", jsonResponseString);
​
            // 4. Parse the JSON response
            try {
                // Attempt to parse the extracted string as a JSON object
                Map<String, String> entities = JSON.parseObject(jsonResponseString, Map.class);
                log.info("成功解析实体: {}", entities);
                return entities != null ? entities : Collections.emptyMap();
            } catch (JSONException e) {
                log.error("无法将提取到的字符串解析为 JSON Map<String, String>: '{}'。错误: {}", jsonResponseString, e.getMessage());
                return Collections.emptyMap(); // Return empty map on parsing failure
            }
​
        } catch (Exception e) {
            log.error("调用 Ollama 模型进行实体提取时出错: {}", e.getMessage(), e);
            return Collections.emptyMap(); // Return empty map on LLM call failure
        }
    }
}
​

这里举例就是使用大模型进行关键词提取,但是提示词目前设计的还不行,模型会胡乱总结关键词,风马牛不相及,所以直接给出该关键词提取的使用方法用于参考:

typescript 复制代码
@Test
    public void testExtractEntities() {
        log.info("--- 开始实体提取测试 ---");
​
        // 1. 准备输入文本
        String inputText = "我计划下周去北京出差,拜访一下阿里巴巴的张三,顺便了解下 Spring AI 的最新进展。";
​
        // 2. 打印输入
        log.info("输入文本: [{}]", inputText);
​
        // 3. 调用实体提取方法
        log.info("调用 LlmEntityExtractor.extractEntities()...");
        Map<String, String> entities = llmEntityExtractor.extractEntities(inputText);
​
        // 4. 打印输出
        log.info("--- 提取结果 (Map) ---");
        if (entities != null && !entities.isEmpty()) {
            log.info("{}", entities);
        } else if (entities != null && entities.isEmpty()) {
            log.warn("提取结果为空 Map。");
        } else {
            // 这通常不应该发生,除非 extractEntities 内部逻辑有变动返回 null
            log.error("实体提取方法返回了 null Map!");
        }
​
        // 5. 添加断言
        assertNotNull("提取结果 Map 不应为 null", entities);
        log.info("--- 实体提取测试结束 ---");
        KeyInformationManager keyInformationManager = new KeyInformationManager();
        keyInformationManager.updateEntities(entities);
        keyInformationManager.getContext();
    }
ini 复制代码
25-04-22.12:04:30.810 [main            ] INFO  LlmEntityExtractor     - 处理 think 块后用于 JSON 解析的字符串: [{"topic": "北京", "person": "张三"}]
25-04-22.12:04:30.881 [main            ] INFO  LlmEntityExtractor     - 成功解析实体: {person=张三, topic=北京}
25-04-22.12:04:30.881 [main            ] INFO  EntityExtractorTest    - --- 提取结果 (Map) ---
25-04-22.12:04:30.881 [main            ] INFO  EntityExtractorTest    - {person=张三, topic=北京}
25-04-22.12:04:30.881 [main            ] INFO  EntityExtractorTest    - --- 实体提取测试结束 ---

可以看出,总结的关键词有点不尽人意,还待优化。方向有:1.根据行业特点总结出常用关键词并且在提示词中进行限定、2.更换更好的自然语言处理模型

1.3 分层摘要法(Hierarchical Summarization)

1.3.1 技术原理

将对话历史分组(例如每5条消息一组),对每组生成摘要,仅保留最近的K个摘要和未摘要的最新消息。这种方法通过压缩历史信息节省令牌。

1.3.2 方法优缺点

  • 优点:保留早期对话的概要信息,适合长对话
  • 缺点:摘要质量依赖模型或算法,可能丢失细节

1.3.3 适用场景

长对话、需要历史上下文的问答系统

这个方法我在设计过程中是配合滑动窗口进行使用,这样可以缓解滑动窗口早期信息的丢失问题。

分层摘要管理器:

typescript 复制代码
@Slf4j
public class HierarchicalConversationManager {
    private int messagesPerSummary;
    private int maxSummaries;
    private Summarizer summarizer;
    private List<String> summaries;
    private List<String> currentMessages;
​
    /**
     * 初始化分层对话管理器。
     * @param messagesPerSummary 每组摘要的消息数
     * @param maxSummaries 最大保留的摘要数
     * @param summarizer 摘要器
     */
    public HierarchicalConversationManager(int messagesPerSummary, int maxSummaries, Summarizer summarizer) {
        this.messagesPerSummary = messagesPerSummary;
        this.maxSummaries = maxSummaries;
        this.summarizer = summarizer;
        this.summaries = new ArrayList<>();
        this.currentMessages = new ArrayList<>();
    }
​
    /**
     * 添加新消息,达到分组大小时生成摘要。
     * @param message 新消息
     */
    public void addMessage(String message) {
        currentMessages.add(message);
        if (currentMessages.size() >= messagesPerSummary) {
            String summary = summarizer.summarize(currentMessages);
            summaries.add(summary);
            currentMessages.clear();
            if (summaries.size() > maxSummaries) {
                summaries.remove(0);
            }
        }
    }
​
    /**
     * 获取当前上下文(摘要+最新消息)。
     * @return 上下文列表
     */
    public List<String> getContext() {
        List<String> context = new ArrayList<>(summaries);
        context.addAll(currentMessages);
        return context;
    }
​
    /**
     * 仅获取摘要
     *  @return 摘要列表
     */
    public List<String> getSummaries() {
        return new ArrayList<>(summaries);
    }
}

摘要提取器:

typescript 复制代码
public interface Summarizer {
​
    /**
     * 对消息列表生成摘要。
     * @param messages 消息列表
     * @return 摘要字符串
     */
    String summarize(List<String> messages);
}
ini 复制代码
// TODO 后续可以考虑回答更快的模型,不然的话会影响整体对话的进度
@Slf4j
@Component
public class LlmSummarizer implements Summarizer{
​
    @Resource
    private OllamaChatClient ollamaChatClient;
​
    private static final String SYSTEM_PROMPT = """
            你是专业的文本摘要助手。
            你的任务是为用户提供的对话消息列表生成一个简洁、准确的摘要。
            专注于对话中的主要观点和关键信息。
            
            重要提示:你的回复必须严格遵守以下格式要求:
            1.  只输出摘要文本本身,内容简明扼要,尽量在几句话以内,不要照搬对话原文。
            2.  绝对不要包含任何介绍性短语,例如"这是摘要:"、"摘要如下:"等。
            3.  绝对不要添加任何问候语、解释、或其他与摘要内容无关的文字。
            4.  你的整个回复内容必须且只能是生成的摘要。
            """;
​
    @Override
    public String summarize(List<String> messages) {
        if (messages == null || messages.isEmpty()) {
            log.warn("摘要消息列表为空,无法生成摘要。");
            return "";
        }
​
        SystemMessage systemMessage = new SystemMessage(SYSTEM_PROMPT);
​
        String conversationContent = messages.stream()
                .map(msg -> "- " + msg)
                .collect(Collectors.joining("\n"));
        UserMessage userMessage = new UserMessage("请为以下对话生成摘要:\n\n" + conversationContent);
​
        List<Message> promptMessages = new ArrayList<>();
        promptMessages.add(systemMessage);
        promptMessages.add(userMessage);
​
        log.info("调用 Ollama 模型进行摘要...");
        try {
            ChatResponse chatResponse = ollamaChatClient.call(new Prompt(promptMessages, OllamaOptions.create().withModel("deepseek-r1:1.5b")));
​
            String rawContent = chatResponse.getResult().getOutput().getContent();
            log.info("LLM 返回的原始完整内容: [{}]", rawContent);
            String jsonResponseString = LlmResponseUtils.extractContentAfterThinkBlock(rawContent);
            log.info("处理 think 块后用于 JSON 解析的字符串: [{}]", jsonResponseString);
            return jsonResponseString.trim();
        } catch (Exception e) {
            log.error("调用 Ollama 模型进行摘要时出错: {}", e.getMessage(), e);
            return "";
        }
    }
}

1.4 多轮对话综合实验v1(滑动窗口+分层摘要)

java 复制代码
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class MultiTurnChatTest {
​
    @Resource
    private OllamaChatClient ollamaChatClient;
​
    @Resource
    private PgVectorStore pgVectorStore;
​
    @Resource
    private LlmEntityExtractor llmEntityExtractor;
​
    @Resource
    private LlmSummarizer llmSummarizer;
​
​
    // We create these locally as their state is managed per test run
    // private KeyInformationManager keyInformationManager = new KeyInformationManager();
    // private ConversationManager conversationManager = new ConversationManager(5); // Keep last 5 messages (adjust as needed)
​
    // System Prompt Template instructing the LLM on how to use the context
    private static final String SYSTEM_PROMPT_TEMPLATE = """
            你是一个智能助手。请根据以下信息回答用户的问题:
            
            1.  **对话历史:** 这是你和用户之前的对话记录。
            {history}
            
            2.  **相关文档:** 这是从知识库中检索到的与用户当前问题可能相关的文档片段。
            {retrieved_docs}
            
            3.  **摘要:** 这是之前的对话记录的摘要,它总结了对话的主要内容。
            {summary}
            
            
            请综合利用以上所有信息,生成一个连贯、准确且有帮助的回复。
            如果相关文档或关键信息中没有足够信息来回答问题,请说明你不知道,不要编造答案。
            请使用中文回答。
            """;
​
    @Test
    public void simulateMultiTurnConversation() {
        log.info("--- 开始模拟多轮对话测试 ---");
​
        // --- 初始化管理器 ---
        HierarchicalConversationManager hierarchicalConversationManager = new HierarchicalConversationManager(1, 2, this.llmSummarizer); // 这里在实际使用可以存放多一点的摘要长度,尽量保存多一些早期信息。
        ConversationManager conversationManager = new ConversationManager(6); // 包含用户和助手,所以窗口需要是偶数
        KeyInformationManager keyInformationManager = new KeyInformationManager();
        String knowledgeBaseName = "知识库1"; // 与 uploadSlidingWindowSentences 中使用的名称一致
​
        // --- 模拟对话轮次 ---
        List<String> userInputs = List.of(
                "你好,我想了解沃卞得这个公司是做什么的?",
                "沃卞得企业社会责任?",
                "这个公司成立于哪一年?", // This might be in the vector store
                "未来三年的计划是什么?"
        );
​
        for (int turn = 0; turn < userInputs.size(); turn++) {
            String currentUserMessage = userInputs.get(turn);
            log.info("\n===== 对话轮次 {} =====", turn + 1);
            log.info("用户输入: [{}]", currentUserMessage);
​
            // 2. 向量数据库检索
            log.debug("--- 向量数据库检索 ---");
            // 使用当前用户消息进行检索
            SearchRequest searchRequest = SearchRequest.query(currentUserMessage)
                    .withTopK(3) // 获取前 3 个最相关的文档
                    .withFilterExpression("knowledgeBase == '" + knowledgeBaseName + "'");
            List<Document> retrievedDocs = pgVectorStore.similaritySearch(searchRequest);
            String retrievedDocsContext = "无";
            String contentForEntityExtraction = ""; // 用于实体提取的内容
            if (!retrievedDocs.isEmpty()) {
                log.info("检索到 {} 个相关文档:", retrievedDocs.size());
                List<String> contents = new ArrayList<>();
                for(Document doc : retrievedDocs) {
                     log.info("  - [Metadata: {}], Content: {}", doc.getMetadata(), doc.getContent().substring(0, Math.min(100, doc.getContent().length())) + "...");
                     contents.add(doc.getContent());
                }
                retrievedDocsContext = String.join("\n---\n", contents);
                contentForEntityExtraction = String.join("\n", contents); // 合并内容用于实体提取
            } else {
                log.info("未检索到相关文档。");
            }
​
//            // 3. 从检索到的文档中提取实体并更新关键信息 (移动到检索之后)
//            log.debug("--- 从检索结果中提取实体 ---");
//            if (!contentForEntityExtraction.isEmpty()) {
//                Map<String, String> extractedEntities = llmEntityExtractor.extractEntities(contentForEntityExtraction);
//                if (!extractedEntities.isEmpty()) {
//                    log.info("从检索结果中提取到的实体: {}", extractedEntities);
//                    keyInformationManager.updateEntities(extractedEntities);
//                    log.info("更新后关键信息上下文:\n{}", keyInformationManager.getContext().toString());
//                } else {
//                    log.info("未从检索结果中提取到实体。");
//                }
//            } else {
//                 log.info("无检索结果,跳过实体提取。");
//            }
​
            // 4. 获取对话历史和摘要 (原步骤3)
            log.debug("--- 获取对话历史以及摘要 ---");
            List<String> history = conversationManager.getHistory();
            String historyContext = history.isEmpty() ? "无历史对话。" : String.join("\n", history);
            String summary = hierarchicalConversationManager.getSummaries().isEmpty()? "无摘要。" : String.join("\n", hierarchicalConversationManager.getContext());
            log.info("当前对话历史上下文:\n{}", historyContext);
            log.info("当前摘要上下文:\n{}", summary);
​
            // 5. 构建 Prompt (原步骤4)
            log.debug("--- 构建 Prompt ---");
            Map<String, Object> promptContext = new HashMap<>();
            promptContext.put("history", historyContext);
            promptContext.put("retrieved_docs", retrievedDocsContext);
            promptContext.put("summary", summary);
//            promptContext.put("key_info", keyInformationManager.getContext().isEmpty() ? "无" : keyInformationManager.getContext());
​
            SystemMessage systemMessage = (SystemMessage) new SystemPromptTemplate(SYSTEM_PROMPT_TEMPLATE).createMessage(promptContext);
            UserMessage userMessage = new UserMessage(currentUserMessage);
            List<Message> promptMessages = List.of(systemMessage, userMessage);
​
            // 6. 调用大模型 (原步骤5)
            log.debug("--- 调用大模型 ---");
            try {
                ChatResponse chatResponse = ollamaChatClient.call(new Prompt(promptMessages, OllamaOptions.create().withModel("deepseek-r1:1.5b")));
                String aiResponse = chatResponse.getResult().getOutput().getContent().trim();
                log.info("助手回复: [{}]", aiResponse);
​
                // 7. 更新对话历史 (原步骤6)
                aiResponse = LlmResponseUtils.extractContentAfterThinkBlock(aiResponse);
                conversationManager.addMessage("用户: " + currentUserMessage);
                conversationManager.addMessage("助手: " + aiResponse);
                List<String> conversationHistory = Arrays.asList(
                        "用户: " + currentUserMessage,
                        "助手: " + aiResponse
                );
                hierarchicalConversationManager.addMessage(conversationHistory.toString());
​
            } catch (Exception e) {
                log.error("调用 Ollama ChatClient 时出错: {}", e.getMessage(), e);
                // Optionally add placeholder to history or break
                conversationManager.addMessage("用户: " + currentUserMessage);
                conversationManager.addMessage("助手: (发生错误,无法回复)");
            }
        }
​
        log.info("\n===== 模拟多轮对话测试结束 =====");
    }
} 

1.4.1 实验流程

综合实验的整体逻辑如下:

  1. 定义系统提示词模板,预留历史对话、相关文档和摘要的占位符
  2. 根据向量相似度查询最相关的k个知识库文档
  3. 提问前检查并获取历史对话和摘要信息
  4. 构建完整提示词并调用大模型生成回复
  5. 保存本轮对话到滑动窗口管理器,同时生成摘要并保存到分层摘要管理器

运行效果:

ini 复制代码
===== 对话轮次 1 =====
25-04-22.12:17:24.605 [main            ] INFO  MultiTurnChatTest      - 用户输入: [你好,我想了解沃卞得这个公司是做什么的?]
25-04-22.12:17:25.357 [main            ] INFO  MultiTurnChatTest      - 检索到 3 个相关文档:
25-04-22.12:17:25.357 [main            ] INFO  MultiTurnChatTest      -   - [Metadata: {originText=在医疗领域,公司与协和医院合作开发的AI辅助诊断系统,在肺结节筛查方面达到三甲医院主任医师水平。, sourceFile=./data/introduction.md, knowledgeBase=知识库1, windowEndIndex=8, windowStartIndex=6, middleSentenceIndex=7, distance=0.22370613}], Content: 其中,智慧城市解决方案已落地30余个城市,实现交通违法识别准确率98.7%,应急救援响应时间缩短40%。 在医疗领域,公司与协和医院合作开发的AI辅助诊断系统,在肺结节筛查方面达到三甲医院主任医师水平...
25-04-22.12:17:25.357 [main            ] INFO  MultiTurnChatTest      -   - [Metadata: {originText=公司总部位于深圳,在北京、上海、硅谷设立研发中心,业务覆盖全球20余个国家和地区,致力于通过自主研发的AI技术平台推动传统产业智能化升级,在计算机视觉、自然语言处理、智能决策系统等领域持续突破,已获得136项技术专利。, sourceFile=./data/introduction.md, knowledgeBase=知识库1, windowEndIndex=2, windowStartIndex=0, middleSentenceIndex=1, distance=0.2888798}], Content: 沃卞得智能科技有限公司:以AI重塑产业未来的创新先锋
​
沃卞得智能科技有限公司成立于2018年,是一家以人工智能技术为核心驱动力的创新型科技企业。 公司总部位于深圳,在北京、上海、硅谷设立研发中心...
25-04-22.12:17:25.357 [main            ] INFO  MultiTurnChatTest      -   - [Metadata: {originText=技术实力方面,公司构建了"天枢"AI中台系统,集成深度学习框架、智能数据标注工具和模型优化模块,可将算法研发效率提升60%。, sourceFile=./data/introduction.md, knowledgeBase=知识库1, windowEndIndex=3, windowStartIndex=1, middleSentenceIndex=2, distance=0.29031676}], Content: 公司总部位于深圳,在北京、上海、硅谷设立研发中心,业务覆盖全球20余个国家和地区,致力于通过自主研发的AI技术平台推动传统产业智能化升级,在计算机视觉、自然语言处理、智能决策系统等领域持续突破,已获得...
25-04-22.12:17:25.357 [main            ] INFO  MultiTurnChatTest      - 当前对话历史上下文:
无历史对话。
25-04-22.12:17:25.357 [main            ] INFO  MultiTurnChatTest      - 当前摘要上下文:
无摘要。
25-04-22.12:19:46.949 [main            ] INFO  MultiTurnChatTest      - 助手回复: [<think>
好,我需要根据用户的问题和提供的信息生成一个连贯的回答。用户的查询是"沃卞得这个公司是做什么的?"。首先,我要查看相关的文档和关键信息。
​
从知识库中,我知道沃卞得智能科技有限公司以AI技术为核心,专注于智能制造、智慧金融、智慧城市和智慧医疗四大领域。还有他们在数据挖掘、模式识别、系统优化等方面的技术实力,比如构建了"天枢"AI中台系统,并获得136项专利。
​
另外,在技术实力部分提到他们构建了一个"天枢"AI中台系统,可提升算法研发效率60%。核心团队由顶尖高校和机构组成,研发人员占比高,发表过多篇国际会议论文。这些都是关键点,能回答用户的问题。
​
所以,我应该将这些信息整合起来,说明公司主要围绕AI技术在智能制造、智慧金融、智慧城市和智慧医疗中的应用展开,并详细描述他们的技术和团队优势。
</think>
​
沃卞得智能科技有限公司以人工智能技术为核心驱动力,专注于通过自主研发的AI技术平台推动传统产业智能化升级。他们在计算机视觉、自然语言处理、智能决策系统等领域取得了显著突破,获得136项技术专利。公司构建了"天枢"AI中台系统,可提升算法研发效率60%。核心团队由顶尖高校和机构组成,研发人员占比达75%,在国际顶级会议如CVPR、NeurIPS发表42篇论文。]
25-04-22.12:19:46.950 [main            ] INFO  LlmSummarizer          - 调用 Ollama 模型进行摘要...
25-04-22.12:21:30.264 [main            ] INFO  LlmSummarizer          - LLM 返回的原始完整内容: [<think>
好的,用户希望我为他们的对话生成一个简洁的摘要。首先,我要仔细阅读对话内容,抓住主要信息。
​
对话中,用户询问了沃卞得公司的业务范围,助理给出了详细的回答。助理提到了公司以人工智能为核心,专注于计算机视觉、自然语言处理等领域的技术突破,并提到获得了136项专利和构建了"天枢"AI中台系统,还提到了研发团队的规模和技术影响力。
​
接下来,我需要提取关键点:公司的驱动力是AI技术,主要业务领域包括计算机视觉、自然语言处理及智能决策系统。获得的专利数量以及研发成果,如"天枢"系统和42项论文,以及核心团队的技术实力和国际会议上的发表数量。这些都是生成摘要的核心信息。
​
然后,我要将这些点组织成几句话,保持简洁且涵盖主要观点。避免使用任何介绍性语言或添加无关内容。确保每个段落集中讲一个重点,比如公司的核心竞争力、技术突破、研发团队和专利成果等。
​
最后,整合这些信息,形成一个逻辑清晰、结构合理的摘要,确保用户能够快速获得所需信息。
</think>
​
沃卞得智能科技有限公司以人工智能为核心,专注于通过自主研发的AI技术平台推动传统产业智能化升级。公司在计算机视觉、自然语言处理及智能决策系统等领域取得了显著突破,并获得了136项技术专利。构建了"天枢"AI中台系统,提升了算法研发效率60%。核心团队由顶尖高校和机构组成,研发人员占比达75%,在国际顶级会议如CVPR、NeurIPS发表42篇论文。]
25-04-22.12:21:30.264 [main            ] INFO  LlmSummarizer          - 处理 think 块后用于 JSON 解析的字符串: [沃卞得智能科技有限公司以人工智能为核心,专注于通过自主研发的AI技术平台推动传统产业智能化升级。公司在计算机视觉、自然语言处理及智能决策系统等领域取得了显著突破,并获得了136项技术专利。构建了"天枢"AI中台系统,提升了算法研发效率60%。核心团队由顶尖高校和机构组成,研发人员占比达75%,在国际顶级会议如CVPR、NeurIPS发表42篇论文。]
​
ini 复制代码
===== 对话轮次 2 =====
25-04-22.12:21:30.264 [main            ] INFO  MultiTurnChatTest      - 用户输入: [沃卞得企业社会责任?]
25-04-22.12:21:30.742 [main            ] INFO  MultiTurnChatTest      - 检索到 3 个相关文档:
25-04-22.12:21:30.742 [main            ] INFO  MultiTurnChatTest      -   - [Metadata: {originText=企业社会责任方面,公司发起"AI赋能乡村振兴"计划,在农产品质量检测、病虫害预警等领域提供技术支持,累计培训乡村技术员1200人次。, sourceFile=./data/introduction.md, knowledgeBase=知识库1, windowEndIndex=12, windowStartIndex=10, middleSentenceIndex=11, distance=0.3390775}], Content: 2022年推出的AlaaS(AI as a Service)平台,通过模块化服务降低企业AI应用门槛,当年即实现150%用户增长。 企业社会责任方面,公司发起"AI赋能乡村振兴"计划,在农产品质量检测...
25-04-22.12:21:30.743 [main            ] INFO  MultiTurnChatTest      -   - [Metadata: {originText=2023年入选国家人工智能社会治理实验基地,参与制定3项行业标准。, sourceFile=./data/introduction.md, knowledgeBase=知识库1, windowEndIndex=13, windowStartIndex=11, middleSentenceIndex=12, distance=0.38030177}], Content: 企业社会责任方面,公司发起"AI赋能乡村振兴"计划,在农产品质量检测、病虫害预警等领域提供技术支持,累计培训乡村技术员1200人次。 2023年入选国家人工智能社会治理实验基地,参与制定3项行业标准。...
25-04-22.12:21:30.743 [main            ] INFO  MultiTurnChatTest      -   - [Metadata: {originText=在医疗领域,公司与协和医院合作开发的AI辅助诊断系统,在肺结节筛查方面达到三甲医院主任医师水平。, sourceFile=./data/introduction.md, knowledgeBase=知识库1, windowEndIndex=8, windowStartIndex=6, middleSentenceIndex=7, distance=0.43061587}], Content: 其中,智慧城市解决方案已落地30余个城市,实现交通违法识别准确率98.7%,应急救援响应时间缩短40%。 在医疗领域,公司与协和医院合作开发的AI辅助诊断系统,在肺结节筛查方面达到三甲医院主任医师水平...
25-04-22.12:21:30.743 [main            ] INFO  MultiTurnChatTest      - 当前对话历史上下文:
用户: 你好,我想了解沃卞得这个公司是做什么的?
助手: 沃卞得智能科技有限公司以人工智能技术为核心驱动力,专注于通过自主研发的AI技术平台推动传统产业智能化升级。他们在计算机视觉、自然语言处理、智能决策系统等领域取得了显著突破,获得136项技术专利。公司构建了"天枢"AI中台系统,可提升算法研发效率60%。核心团队由顶尖高校和机构组成,研发人员占比达75%,在国际顶级会议如CVPR、NeurIPS发表42篇论文。
25-04-22.12:21:30.743 [main            ] INFO  MultiTurnChatTest      - 当前摘要上下文:
沃卞得智能科技有限公司以人工智能为核心,专注于通过自主研发的AI技术平台推动传统产业智能化升级。公司在计算机视觉、自然语言处理及智能决策系统等领域取得了显著突破,并获得了136项技术专利。构建了"天枢"AI中台系统,提升了算法研发效率60%。核心团队由顶尖高校和机构组成,研发人员占比达75%,在国际顶级会议如CVPR、NeurIPS发表42篇论文。
25-04-22.12:24:20.985 [main            ] INFO  MultiTurnChatTest      - 助手回复: [<think>
好吧,用户问的是"沃卞得企业社会责任?"我先回忆一下对话历史。在之前的对话里,助手已经详细介绍了沃卞得公司的情况,包括AI技术、市场表现和核心团队。特别是他们提到的"AI赋能乡村振兴"计划,在农产品检测和病虫害预警领域做了不少工作,并且参与了行业标准制定。
​
现在用户明确询问企业社会责任部分,我需要把相关的信息整合起来。助手已经分成了几个方面:智慧城市解决方案,医疗领域合作开发的辅助诊断系统,以及商业模式的双轮驱动。这些内容都符合企业的社会责任目标,比如技术应用、公共卫生、经济发展等方面。
​
另外,沃卞得在国际顶级会议发表论文,这显示了他们的国际影响力和学术水平,这也支持他们在社会责任方面有积极贡献。团队的顶尖机构和研发人员比例高,说明他们有能力推动社会进步。
​
综合以上信息,我应该把每个部分提到的内容详细一点,结构清晰,让用户一目了然。同时,确保回答准确,不编造内容,避免遗漏重要细节。
</think>
​
沃卞得企业社会责任方面主要体现在以下几个方面:
​
1. **技术应用于解决公共卫生问题**:在农产品质量检测、病虫害预警等领域,与协和医院合作开发AI辅助诊断系统,累计培训乡村技术员1200人次。这些技术的应用为村庄居民提供支持,助力乡村振兴。
​
2. **推动智慧金融的发展**:沃卞得与智慧金融行业紧密合作,构建"技术底座+行业套件"的商业模式,形成智能制造、智慧金融、智慧城市和智慧医疗四大垂直领域解决方案。
​
3. **推动城市交通的智能化发展**:公司在交通违法识别准确率方面达到了98.7%,应急救援响应时间缩短了40%。这些技术的应用提升了城市的公共安全水平,促进了社会进步。
​
总的来说,沃卞得积极响应国家"人工智能赋能乡村振兴"的号召,通过AI技术解决公共卫生问题,并推动智慧金融和城市交通的智能化发展,展现了在企业社会责任中的积极作用。]
25-04-22.12:24:20.985 [main            ] INFO  LlmSummarizer          - 调用 Ollama 模型进行摘要...

2 总结与未来展望

2.1 现有方案局限性

当前实现存在以下局限性,也是未来的主要改进方向:

句子-滑动窗口的局限性:需要知识文档按照中文语法来写的,如果别人不用句号之类的进行结尾,那就麻烦了。所以这个问题需要考虑到,从这也能看出,直接分割的好处,就不需要考虑这些问题。

滑动窗口的局限性:容易丢失早期信息,但这个可以用分层摘要缓解

分层摘要的局限性:调用大模型形成摘要的时候会很慢,后续可以引入线程

关键词的局限性:模型总结的关键词范围太大,可用性较低。

2.2 上下文存储策略

根据腾讯元宝等对话系统的使用经验,上下文信息通常具有有效期限制。下一步将探索如何设计用户问答结果记录表,包括以下关键字段:

  • 对话ID(唯一标识)
  • 用户ID
  • 上下文创建时间
  • 上下文过期时间
  • 上下文内容摘要
  • 关联知识库ID
  • 对话状态标记

接下来就要探索,如何设计用户问答的结果记录表,包括哪些字段等问题

相关推荐
郑道44 分钟前
Docker 在 macOS 下的安装与 Gitea 部署经验总结
后端
3Katrina1 小时前
妈妈再也不用担心我的课设了---Vibe Coding帮你实现期末课设!
前端·后端·设计
汪子熙1 小时前
HSQLDB 数据库锁获取失败深度解析
数据库·后端
高松燈1 小时前
若伊项目学习 后端分页源码分析
后端·架构
没逻辑2 小时前
主流消息队列模型与选型对比(RabbitMQ / Kafka / RocketMQ)
后端·消息队列
倚栏听风雨2 小时前
SwingUtilities.invokeLater 详解
后端
Java中文社群2 小时前
AI实战:一键生成数字人视频!
java·人工智能·后端
王中阳Go3 小时前
从超市收银到航空调度:贪心算法如何破解生活中的最优决策谜题?
java·后端·算法
shepherd1113 小时前
谈谈TransmittableThreadLocal实现原理和在日志收集记录系统上下文实战应用
java·后端·开源
关山月3 小时前
使用 Ollama 和 Next.js 构建 AI 助手
后端