에이전트 메모리

·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 절에서 메모리를 사용할 수도 있습니다. 즉시 사용 가능한 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은 사용자 관련 사실과 프로젝트 관련 사실을 검색하고 개념을 결정한 후 메모리에 저장합니다.

모범 사례

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

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

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