에이전트 메모리

·3분 읽기

원문: 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. 메모리 저장 공간 설정
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)
  1. 사실을 기억에 저장한다
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. 사실 검색
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 절에서 메모리를 사용할 수도 있습니다. 즉시 사용 가능한 loadFactsToAgentsaveFactsFromHistory 상위 수준 추상화는 사실을 기록에 저장하고 기록에서 사실을 로드하며 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은 사용자 관련 사실과 프로젝트 관련 사실을 검색하고 개념을 결정한 후 메모리에 저장합니다.

모범 사례

  1. 간단하게 시작하세요
  • 암호화 없는 기본 저장소로 시작하세요
  • 여러 사실로 이동하기 전에 단일 사실을 사용하십시오.
  1. 잘 정리하세요
  • 명확한 개념 이름을 사용하세요.
  • 유용한 설명 추가
  • 관련 정보를 동일한 주제로 유지
  1. 오류 처리
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 기능에는 극단적인 경우를 처리하기 위한 여러 메커니즘이 포함되어 있습니다.

  1. NoMemory 공급자: 아무것도 저장하지 않는 기본 구현으로, 메모리 공급자가 없을 때 사용됩니다. 지정.

  2. 주제 특정성 처리: 사실을 로드할 때 이 기능은 보다 구체적인 주제의 사실을 우선시합니다. 정의된 priorityLevel을 기반으로 합니다.

  3. 범위 필터링: 관련 정보만 로드되도록 범위별로 사실을 필터링할 수 있습니다.

  4. 타임스탬프 추적: 사실은 생성된 시간을 추적하기 위해 타임스탬프와 함께 저장됩니다.

  5. 팩트 유형 처리: 이 기능은 각 유형에 대한 적절한 처리를 통해 단일 팩트와 다중 팩트를 모두 지원합니다.

API 문서

AgentMemory 기능과 관련된 전체 API 참조는 agents-features-memory 모듈에 대한 참조 문서를 참조하세요.

특정 패키지에 대한 API 문서:

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 유형을 사용하면 됩니다. 개념을 정의할 때 factTypeFactType.MULTIPLE로 설정합니다.

1val concept = Concept(2    keyword = "user-skills",3    description = "Programming languages the user is skilled in",4    factType = FactType.MULTIPLE5)

이를 통해 목록으로 검색되는 개념에 대한 여러 값을 저장할 수 있습니다.