feat(memory): add :memory-md-vector hybrid backend + :reflection-api + outbox/journal entity splits
- :memory-md-vector (KMP jvm+linuxX64+mingwX64): .md-файлы как source of truth, векторный индекс (sqlite-vec) как derived cache. reconcile() на старте: orphan-cleanup + content-hash-gated re-embed. Гибридный скор 0.7*vector + 0.3*keyword. Заменяет EmbeddingProvider на KMP-TextEmbeddingExecutor из :memory-api. - :reflection-api: новый 4-й API-модуль (Reflection, ReflectionStore, ReflectionEvent). Зависит только от :memory-api. - :journal-api получил ConversationRecord/ConversationStore/Ids (бывший :message-store-api, полностью удалён). :outbox-api получил Event, CommonEvent, AgentEvent (бывший :event-store). - :memory-api получил MemoryVectorIndex + NoteMatches + TextEmbeddingExecutor (suspend-обёртка над TextEmbeddingExtractor). - :memory-vector KMP-цели достигнуты через commonMain-only TextEmbedding- Executor, EmbeddingProvider выпилен; :memory-md-vector тянет text-embedding-api транзитивно через :memory-api. - :standalone flatten в commonMain/commonTest завершён (тесты из jvmTest переехали в commonTest). Включён optional деп :memory-md-vector через AGENTIK_MEMORY_BACKEND=md-vector. jvmTest: 96 задач, 407 тестов, 0 падений.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.multiplatform)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
}
|
||||
|
||||
// Public API для хранения self-reflection записей агента. Не зависит от
|
||||
// journal/context/outbox — reflection это отдельная сущность (рантайм-мета
|
||||
// о качестве последних ходов).
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
|
||||
jvm()
|
||||
macosX64()
|
||||
macosArm64()
|
||||
iosX64()
|
||||
iosArm64()
|
||||
iosSimulatorArm64()
|
||||
linuxX64()
|
||||
linuxArm64()
|
||||
mingwX64()
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
api(libs.kotlinx.coroutines.core)
|
||||
api(libs.kotlinx.serialization.core)
|
||||
api(libs.kotlinx.serialization.json)
|
||||
}
|
||||
commonTest.dependencies {
|
||||
implementation(kotlin("test"))
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package pw.binom.agentik.reflection
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlin.time.Instant
|
||||
|
||||
/**
|
||||
* Self-reflection запись — что агент "думает" о качестве своих последних ходов.
|
||||
*
|
||||
* - [score]: 1..5 (самооценка качества)
|
||||
* - [weakSpots]: конкретные слабые места ("медленно ищу в Y", "путаю A и B")
|
||||
* - [summary]: свободный комментарий в markdown (что заметил, что улучшить)
|
||||
*
|
||||
* Источник: one-shot LLM-размышление после каждых N ходов (см. AGENTIK_REFLECTION_INTERVAL).
|
||||
* Используется в `ChatAgent.buildSystemPrompt` как "слабые места за последнее время".
|
||||
*/
|
||||
data class Reflection(
|
||||
val id: String,
|
||||
val conversationId: String?,
|
||||
val createdAt: Instant,
|
||||
val turnsAnalyzed: Int,
|
||||
val score: Int,
|
||||
val summary: String,
|
||||
val weakSpots: List<String>,
|
||||
)
|
||||
|
||||
/**
|
||||
* Хранилище рефлексий. Backed by SQLDelight `reflection` таблицу (impl в
|
||||
* `:storage-sqlite`) или in-memory (impl в `:storage-inmemory`).
|
||||
*
|
||||
* Рефлексии — append-only: старые записи удаляются [deleteOlderThan] (cleanup)
|
||||
* или архивируются через [Curator]-подобный процесс, но не редактируются.
|
||||
*/
|
||||
interface ReflectionStore : AutoCloseable {
|
||||
suspend fun insert(reflection: Reflection)
|
||||
suspend fun get(id: String): Reflection?
|
||||
/** Самые свежие рефлексии (по всему агенту). */
|
||||
suspend fun listRecent(limit: Int = 10): List<Reflection>
|
||||
/** Рефлексии для конкретного диалога. */
|
||||
suspend fun listForConversation(conversationId: String, limit: Int = 10): List<Reflection>
|
||||
suspend fun deleteOlderThan(cutoff: Instant)
|
||||
suspend fun count(): Int
|
||||
|
||||
/** Стрим новых рефлексий для подписчиков (для UI в будущем). */
|
||||
fun events(): Flow<ReflectionEvent> = kotlinx.coroutines.flow.emptyFlow()
|
||||
|
||||
override fun close()
|
||||
}
|
||||
|
||||
sealed interface ReflectionEvent {
|
||||
data class Created(val reflection: Reflection) : ReflectionEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* Генератор id для reflection-записей. Префикс `refl-` чтобы в логах и
|
||||
* БД-схемах было видно сразу.
|
||||
*/
|
||||
object Ids {
|
||||
fun new(): String = "refl-${kotlin.uuid.Uuid.random()}"
|
||||
}
|
||||
Reference in New Issue
Block a user