에이전트 메모리
원문: Koog Documentation — agent-memory 이 글은 Koog 공식 문서의 agent-memory 페이지를 한국어로 옮긴 번역본입니다. 문서 구조와 링크 의미를 유지하되, MkDocs 전용 UI 문법은 블로그에서 읽기 좋도록 정리했습니다.
에이전트 메모리
기능 개요
AgentMemory 기능은 AI 에이전트가 저장, 검색 및 사용할 수 있게 해주는 Koog 프레임워크의 구성 요소입니다. 대화를 통한 정보.
목적
AgentMemory 기능은 다음을 통해 AI 에이전트 상호 작용에서 컨텍스트를 유지하는 문제를 해결합니다.
- 대화에서 추출한 중요한 사실을 저장합니다.
- 개념, 주제 및 범위별로 정보를 구성합니다.
- 향후 상호작용에 필요할 때 관련 정보를 검색합니다.
- 사용자 기본 설정 및 기록을 기반으로 개인화를 활성화합니다.
건축학
AgentMemory 기능은 계층 구조를 기반으로 구축되었습니다. 구조의 요소는 아래 섹션에 나열되고 설명됩니다.
사리
사실은 메모리에 저장된 개별 정보 조각입니다. 사실은 실제로 저장된 정보를 나타냅니다. 사실에는 두 가지 유형이 있습니다.
- SingleFact: 개념과 관련된 단일 값입니다. 예를 들어 IDE 사용자가 현재 선호하는 테마는 다음과 같습니다.
1// Storing favorite IDE theme (single value)2val themeFact = SingleFact(3 concept = Concept(4 "ide-theme", 5 "User's preferred IDE theme", 6 factType = FactType.SINGLE),7 value = "Dark Theme",8 timestamp = Clock.System.now().toEpochMilliseconds(),9)- MultipleFacts: 개념과 관련된 여러 값. 예를 들어 사용자가 아는 모든 언어는 다음과 같습니다.
1// Storing programming languages (multiple values)2val languagesFact = MultipleFacts(3 concept = Concept(4 "programming-languages",5 "Languages the user knows",6 factType = FactType.MULTIPLE7 ),8 values = listOf("Kotlin", "Java", "Python"),9 timestamp = Clock.System.now().toEpochMilliseconds(),10)개념
개념은 관련 메타데이터가 있는 정보 범주입니다.
- 키워드: 개념의 고유 식별자입니다.
- 설명: 개념이 나타내는 내용에 대한 자세한 설명입니다.
- FactType: 개념이 단일 또는 다중 사실을 저장하는지 여부(
FactType.SINGLE또는FactType.MULTIPLE).
과목
주제는 사실과 연관될 수 있는 엔터티입니다.
주제의 일반적인 예는 다음과 같습니다.
- 사용자: 개인 기본 설정 및 설정
- 환경: 애플리케이션의 환경과 관련된 정보
모든 사실에 대한 기본 주제로 사용할 수 있는 사전 정의된 MemorySubject.Everything이 있습니다.
또한 MemorySubject 추상 클래스를 확장하여 사용자 정의 메모리 주제를 정의할 수 있습니다.
1object MemorySubjects {2 /**3 * Information specific to the local machine environment4 * Examples: Installed tools, SDKs, OS configuration, available commands5 */6 @Serializable7 data object Machine : MemorySubject() {8 override val name: String = "machine"9 override val promptDescription: String =10 "Technical environment (installed tools, package managers, packages, SDKs, OS, etc.)"11 override val priorityLevel: Int = 112 }1314 /**15 * Information specific to the user16 * Examples: Conversation preferences, issue history, contact information17 */18 @Serializable19 data object User : MemorySubject() {20 override val name: String = "user"21 override val promptDescription: String =22 "User information (conversation preferences, issue history, contact details, etc.)"23 override val priorityLevel: Int = 124 }25}범위
메모리 범위는 사실이 관련된 컨텍스트입니다.
- 에이전트: 에이전트에만 해당됩니다.
- 기능: 특정 기능에만 해당됩니다.
- 제품: 특정 제품에만 적용됩니다.
- CrossProduct: 여러 제품에 걸쳐 관련됩니다.
구성 및 초기화
이 기능은 AgentMemory 클래스를 통해 에이전트 파이프라인과 통합되어 저장 및
팩트를 로드하며 에이전트 구성의 기능으로 설치될 수 있습니다.
구성
AgentMemory.Config 클래스는 AgentMemory 기능에 대한 구성 클래스입니다.
1class Config(2 var memoryProvider: AgentMemoryProvider = NoMemory,3 var scopesProfile: MemoryScopesProfile = MemoryScopesProfile(),45 var agentName: String,6 var featureName: String,7 var organizationName: String,8 var productName: String9) : FeatureConfig()설치
에이전트에 AgentMemory 기능을 설치하려면 아래 코드 샘플에 제공된 패턴을 따르십시오.
1val agent = AIAgent(2 promptExecutor = simpleOllamaAIExecutor(),3 llmModel = OllamaModels.Meta.LLAMA_3_2,4) {5 install(AgentMemory) {6 memoryProvider = memoryProvider7 agentName = "your-agent-name"8 featureName = "your-feature-name"9 organizationName = "your-organization-name"10 productName = "your-product-name"11 }12}예시 및 빠른 시작
기본 사용법
다음 코드 조각은 메모리 저장소의 기본 설정과 팩트를 저장하고 로드하는 방법을 보여줍니다. 기억.
- 메모리 저장 공간 설정
1// Create a memory provider2val memoryProvider = LocalFileMemoryProvider(3 config = LocalMemoryConfig("customer-support-memory"),4 storage = SimpleStorage(JVMFileSystemProvider.ReadWrite),5 fs = JVMFileSystemProvider.ReadWrite,6 root = Path("path/to/memory/root")7)- 사실을 기억에 저장한다
1memoryProvider.save(2 fact = SingleFact(3 concept = Concept("greeting", "User's name", FactType.SINGLE),4 value = "John",5 timestamp = Clock.System.now().toEpochMilliseconds(),6 ),7 subject = MemorySubjects.User,8 scope = MemoryScope.Product("my-app"),9)- 사실 검색
1// Get the stored information2val greeting = memoryProvider.load(3 concept = Concept("greeting", "User's name", FactType.SINGLE),4 subject = MemorySubjects.User,5 scope = MemoryScope.Product("my-app")6)7if (greeting.size > 1) {8 println("Memories found: ${greeting.joinToString(", ")}")9} else {10 println("Information not found. First time here?")11}메모리 노드 사용
AgentMemory 기능은 에이전트 전략에 사용할 수 있는 다음과 같은 사전 정의된 메모리 노드를 제공합니다.
- nodeLoadAllFactsFromMemory: 주어진 개념에 대한 메모리에서 주제에 대한 모든 사실을 로드합니다.
- nodeLoadFromMemory: 주어진 개념에 대해 메모리에서 특정 사실을 로드합니다.
- nodeSaveToMemory: 사실을 메모리에 저장합니다.
- nodeSaveToMemoryAutoDetectFacts: 채팅 기록에서 사실을 자동으로 감지 및 추출하여 메모리에 저장합니다. LLM을 사용하여 개념을 식별합니다.
다음은 에이전트 전략에서 노드를 구현하는 방법에 대한 예입니다.
1val strategy = strategy("example-agent") {2 // Node to automatically detect and save facts3 val detectFacts by nodeSaveToMemoryAutoDetectFacts<Unit>(4 subjects = listOf(MemorySubjects.User, MemorySubjects.Machine)5 )67 // Node to load specific facts8 val loadPreferences by node<Unit, Unit> {9 withMemory {10 loadFactsToAgent(11 llm = llm,12 concept = Concept("user-preference", "User's preferred programming language", FactType.SINGLE),13 subjects = listOf(MemorySubjects.User)14 )15 }16 }1718 // Connect nodes in the strategy19 edge(nodeStart forwardTo detectFacts)20 edge(detectFacts forwardTo loadPreferences)21 edge(loadPreferences forwardTo nodeFinish)22}메모리를 안전하게 만들기
암호화를 사용하면 민감한 정보가 암호화된 저장소 내부에서 보호되도록 할 수 있습니다. 메모리 공급자.
1// Simple encrypted storage setup2val secureStorage = EncryptedStorage(3 fs = JVMFileSystemProvider.ReadWrite,4 encryption = Aes256GCMEncryptor("your-secret-key")5)예: 사용자 기본 설정 기억
다음은 사용자의 기본 설정을 기억하기 위해 실제 시나리오에서 AgentMemory를 사용하는 방법에 대한 예입니다. 사용자가 가장 좋아하는 프로그래밍 언어.
1memoryProvider.save(2 fact = SingleFact(3 concept = Concept("preferred-language", "What programming language is preferred by the user?", FactType.SINGLE),4 value = "Kotlin",5 timestamp = Clock.System.now().toEpochMilliseconds(),6 ),7 subject = MemorySubjects.User,8 scope = MemoryScope.Product("my-app")9)고급 사용법
메모리가 있는 사용자 정의 노드
모든 노드 내부의 withMemory 절에서 메모리를 사용할 수도 있습니다. 즉시 사용 가능한 loadFactsToAgent 및 saveFactsFromHistory 상위 수준 추상화는 사실을 기록에 저장하고 기록에서 사실을 로드하며 LLM 채팅을 업데이트합니다.
1val loadProjectInfo by node<Unit, Unit> {2 withMemory {3 loadFactsToAgent(4 llm = llm,5 concept = Concept("preferred-language", "What programming language is preferred by the user?", FactType.SINGLE)6 )7 }8}910val saveProjectInfo by node<Unit, Unit> {11 withMemory {12 saveFactsFromHistory(13 llm = llm,14 concept = Concept("preferred-language", "What programming language is preferred by the user?", FactType.SINGLE),15 subject = MemorySubjects.User,16 scope = MemoryScope.Product("my-app")17 )18 }19}자동 사실 탐지
nodeSaveToMemoryAutoDetectFacts 방법을 사용하여 에이전트 기록에서 모든 사실을 감지하도록 LLM에 요청할 수도 있습니다.
1val saveAutoDetect by nodeSaveToMemoryAutoDetectFacts<Unit>(2 subjects = listOf(MemorySubjects.User, MemorySubjects.Machine)3)위의 예에서 LLM은 사용자 관련 사실과 프로젝트 관련 사실을 검색하고 개념을 결정한 후 메모리에 저장합니다.
모범 사례
- 간단하게 시작하세요
- 암호화 없는 기본 저장소로 시작하세요
- 여러 사실로 이동하기 전에 단일 사실을 사용하십시오.
- 잘 정리하세요
- 명확한 개념 이름을 사용하세요.
- 유용한 설명 추가
- 관련 정보를 동일한 주제로 유지
- 오류 처리
1try {2 memoryProvider.save(fact, subject, scope)3} catch (e: Exception) {4 println("Oops! Couldn't save: ${e.message}")5}오류 처리에 대한 자세한 내용은 Error handling and edge cases을 참조하세요.
오류 처리 및 극단적인 경우
AgentMemory 기능에는 극단적인 경우를 처리하기 위한 여러 메커니즘이 포함되어 있습니다.
NoMemory 공급자: 아무것도 저장하지 않는 기본 구현으로, 메모리 공급자가 없을 때 사용됩니다. 지정.
주제 특정성 처리: 사실을 로드할 때 이 기능은 보다 구체적인 주제의 사실을 우선시합니다. 정의된
priorityLevel을 기반으로 합니다.범위 필터링: 관련 정보만 로드되도록 범위별로 사실을 필터링할 수 있습니다.
타임스탬프 추적: 사실은 생성된 시간을 추적하기 위해 타임스탬프와 함께 저장됩니다.
팩트 유형 처리: 이 기능은 각 유형에 대한 적절한 처리를 통해 단일 팩트와 다중 팩트를 모두 지원합니다.
API 문서
AgentMemory 기능과 관련된 전체 API 참조는 agents-features-memory 모듈에 대한 참조 문서를 참조하세요.
특정 패키지에 대한 API 문서:
- ai.koog.agents.local.memory.feature:
AgentMemory클래스와 핵심 구현을 포함합니다. AI 에이전트 메모리 기능. - ai.koog.agents.local.memory.feature.nodes: 다음에서 사용할 수 있는 사전 정의된 메모리 관련 노드를 포함합니다. 하위 그래프.
- ai.koog.agents.local.memory.config: 메모리 작업에 사용되는 메모리 범위 정의를 제공합니다.
- ai.koog.agents.local.memory.model: 핵심 데이터 구조 및 인터페이스의 정의를 포함합니다. 에이전트가 다양한 상황과 기간에 걸쳐 정보를 저장, 구성 및 검색할 수 있게 해줍니다.
- ai.koog.agents.local.memory.feature.history: 검색을 위한 기록 압축 전략을 제공하고 과거 세션 활동이나 저장된 메모리에서 특정 개념에 대한 사실적 지식을 통합합니다.
- ai.koog.agents.local.memory.providers: 구조화된 상황 인식 방식으로 지식을 저장하고 검색하기 위한 기본 작업과 그 구현을 정의하는 핵심 인터페이스를 제공합니다.
- ai.koog.agents.local.memory.storage: 다양한 플랫폼과 스토리지 백엔드 전반에 걸쳐 파일 작업을 위한 핵심 인터페이스와 특정 구현을 제공합니다.
FAQ 및 문제 해결
사용자 정의 메모리 공급자를 어떻게 구현합니까?
사용자 정의 메모리 공급자를 구현하려면 AgentMemoryProvider 인터페이스를 구현하는 클래스를 생성하십시오.
1class MyCustomMemoryProvider : AgentMemoryProvider {2 override suspend fun save(fact: Fact, subject: MemorySubject, scope: MemoryScope) {3 // Implementation for saving facts4 }56 override suspend fun load(concept: Concept, subject: MemorySubject, scope: MemoryScope): List<Fact> {7 // Implementation for loading facts by concept8 }910 override suspend fun loadAll(subject: MemorySubject, scope: MemoryScope): List<Fact> {11 // Implementation for loading all facts12 }1314 override suspend fun loadByDescription(15 description: String,16 subject: MemorySubject,17 scope: MemoryScope18 ): List<Fact> {19 // Implementation for loading facts by description20 }21}여러 주제에서 로드할 때 사실의 우선순위는 어떻게 됩니까?
사실은 주제의 특수성에 따라 우선순위가 지정됩니다. 사실을 로드할 때 동일한 개념에 여러 주제의 사실이 있는 경우 가장 구체적인 주제의 사실이 사용됩니다.
동일한 개념에 대해 여러 값을 저장할 수 있나요?
예, MultipleFacts 유형을 사용하면 됩니다. 개념을 정의할 때 factType을 FactType.MULTIPLE로 설정합니다.
1val concept = Concept(2 keyword = "user-skills",3 description = "Programming languages the user is skilled in",4 factType = FactType.MULTIPLE5)이를 통해 목록으로 검색되는 개념에 대한 여러 값을 저장할 수 있습니다.