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
  • 对话状态标记

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

相关推荐
止语Lab1 小时前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活1 小时前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困1 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn1 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户298698530141 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户77283104908401 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金1 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛2 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构
IT_陈寒2 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
卷无止境2 小时前
提升 Python 代码健壮性的方法大盘点
后端·python