跳转至

长期记忆

功能(实验性)

LongTermMemory 功能通过两组独立的设置,为 Koog AI 智能体添加持久化记忆: - 检索 — 从记忆存储中获取相关上下文,增强 LLM 提示(检索增强生成或 RAG) - 摄取 — 将对话消息持久化到记忆存储中,供未来检索

快速开始

注意: LongTermMemory 是一个实验性的 API。请使用 @OptIn(ExperimentalAgentsApi::class) 注解你的代码,或在文件顶部添加 @file:OptIn(ExperimentalAgentsApi::class)

@OptIn(ExperimentalAgentsApi::class)
val myStorage = InMemoryRecordStorage() // 或你的向量数据库适配器

@OptIn(ExperimentalAgentsApi::class)
val agent = AIAgent(
    promptExecutor = executor,
    strategy = singleRunStrategy(),
    agentConfig = agentConfig,
    toolRegistry = ToolRegistry.EMPTY
) {
    install(LongTermMemory) {
        retrieval {
            storage = myStorage
            searchStrategy = KeywordSearchStrategy(topK = 5)
        }
    }
}

agent.run("我们昨天讨论了什么?")
InMemoryRecordStorage myStorage = new InMemoryRecordStorage();

AIAgent agent = AIAgent.builder()
    .promptExecutor(executor)
    .llmModel(OpenAIModels.Chat.GPT4o)
    .systemPrompt("你是一个乐于助人的助手。")
    .install(LongTermMemory.Feature, config -> {
        config.retrieval(
            new LongTermMemory.RetrievalSettingsBuilder()
                .withStorage(myStorage)
                .withSearchStrategy(query ->
                    new KeywordSearchRequest(query, 15, 0.5, null)
                )
                .build()
        );
    })
    .build();

Object result = agent.run("我们昨天讨论了什么?");

仅检索(RAG

当你有一个预填充的知识库时,可以仅使用检索功能而不进行摄取:

@OptIn(ExperimentalAgentsApi::class)
install(LongTermMemory) {
    retrieval {
        storage = myVectorDbStorage
        namespace = "my-collection"  // 可选:限定到特定的命名空间/集合
        searchStrategy = SimilaritySearchStrategy(topK = 3, similarityThreshold = 0.7)
        promptAugmenter = SystemPromptAugmenter()
    }
}
var retrievalSettings = new LongTermMemory.RetrievalSettingsBuilder()
    .withStorage(myVectorDbStorage)
    .withSearchStrategy(
        SearchStrategy.builder().similarity().withTopK(3).withSimilarityThreshold(0.7).build()
    )
    .withPromptAugmenter(PromptAugmenter.builder().system().build())
    .build();

提示增强器

增强器 行为
SystemPromptAugmenter() 将上下文作为系统消息插入到提示的开头(如果没有系统消息,则不执行任何操作)
UserPromptAugmenter() 将上下文作为单独的用户消息插入到最后一个用户消息之前
PromptAugmenter { prompt, context -> ... } 通过 lambda 表达式进行自定义增强
### 搜索策略 策略 行为 { #search-strategies }
KeywordSearchStrategy() 全文/词法关键词匹配
SimilaritySearchStrategy() 向量相似度语义搜索
query -> new KeywordSearchRequest(query, 20, 0.0, null) 通过 lambda 自定义搜索

仅数据摄取

使用仅摄取(不检索)功能,随时间逐步构建记忆存储:

@OptIn(ExperimentalAgentsApi::class)
install(LongTermMemory) {
    ingestion {
        storage = myVectorDbStorage
        namespace = "my-collection"  // 可选:限定到特定命名空间/集合
        extractor = FilteringMemoryRecordExtractor(
            messageRolesToExtract = setOf(Message.Role.User, Message.Role.Assistant)
        )
        timing = IngestionTiming.ON_LLM_CALL
    }
}
var ingestionSettings = new LongTermMemory.IngestionSettingsBuilder()
    .withStorage(myVectorDbStorage)
    .withExtractor(
        MemoryRecordExtractor.builder()
            .filtering()
            .withExtractRoles(new HashSet<>(Arrays.asList(Message.Role.User, Message.Role.Assistant)))
            .withLastMessageOnly(false)
            .build()
    )
    .withTiming(IngestionTiming.ON_LLM_CALL)
    .build();

摄取时机

时机 行为
ON_LLM_CALL 在每次 LLM 调用/流式处理时摄取消息(支持会话内 RAG
ON_AGENT_COMPLETION 在智能体运行完成时一次性摄取所有消息

从策略节点访问长期记忆

在策略节点内使用 withLongTermMemory { } 直接搜索或添加记录:

@OptIn(ExperimentalAgentsApi::class)
val myNode by node<String, Unit> {
    withLongTermMemory {
        // Manually add records
        val record = MemoryRecord(content = "important fact")
        this.getIngestionStorage()?.add(listOf(record), ingestionSettings?.namespace)

        // Manually search
        val request = SimilaritySearchRequest(query = input, limit = 5)
        val results = this.getRetrievalStorage()?.search(request, retrievalSettings?.namespace)
    }
}

使用 longTermMemory() 直接获取功能实例:

@OptIn(ExperimentalAgentsApi::class)
val myNode by node<String, Unit> {
    val memory = longTermMemory()
    val storage = memory.getIngestionStorage()
}

自定义记忆记录提取器

实现 MemoryRecordExtractor 以控制消息在存储前的转换方式:

@OptIn(ExperimentalAgentsApi::class)
val summarizingExtractor = MemoryRecordExtractor { messages ->
    messages
        .filter { it.role == Message.Role.Assistant }
        .map { MemoryRecord(content = summarize(it.content)) }
}

install(LongTermMemory) {
    ingestion {
        storage = myStorage
        extractor = summarizingExtractor
    }
}

实现自定义存储

实现 RetrievalStorage 和/或 IngestionStorage 以连接到您的向量数据库:

class MyVectorDbStorage : RetrievalStorage, IngestionStorage {
    override suspend fun search(
        request: SearchRequest, namespace: String?
    ): List<SearchResult> {
        // Query your vector DB
    }

    override suspend fun add(
        records: List<MemoryRecord>, namespace: String?
    ) {
        // Upsert into your vector DB
    }
}

用于测试时,可使用内置的 InMemoryRecordStorage,该存储将记录保留在内存中并支持基于关键词的搜索。