动态上下文管理学习记录
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 实验流程
综合实验的整体逻辑如下:
- 定义系统提示词模板,预留历史对话、相关文档和摘要的占位符
- 根据向量相似度查询最相关的k个知识库文档
- 提问前检查并获取历史对话和摘要信息
- 构建完整提示词并调用大模型生成回复
- 保存本轮对话到滑动窗口管理器,同时生成摘要并保存到分层摘要管理器
运行效果:
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
- 对话状态标记

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