{"name":"Marian","description":"AI-first knowledge workspace: linked notes, knowledge graph, hybrid retrieval, agents.","url":"https://memory.maria-code.ai","language":["ja","en"],"keywords":["Marian","knowledge workspace","second brain","linked notes","knowledge graph","wiki links","context engineering","hybrid retrieval","RAG","AI agents","Next.js","Supabase","ナレッジマネジメント","ナレッジグラフ","セカンドブレイン"],"endpoints":{"blog":"https://memory.maria-code.ai/blog","llmsTxt":"https://memory.maria-code.ai/llms.txt","llmsFullTxt":"https://memory.maria-code.ai/llms-full.txt","feed":"https://memory.maria-code.ai/feed.xml","sitemap":"https://memory.maria-code.ai/sitemap.xml"},"pages":[{"url":"https://memory.maria-code.ai","title":"Marian — AI Knowledge Workspace","description":"Marian is an AI-first knowledge workspace for linked notes, knowledge graphs, hybrid retrieval, research, and agents — on desktop and mobile."},{"url":"https://memory.maria-code.ai/workspace","title":"Desktop Workspace","description":"The Marian desktop workspace: linked Markdown notes, file tree, command palette, and every knowledge view in one state machine."},{"url":"https://memory.maria-code.ai/mobile","title":"Mobile App","description":"Marian on the phone: the same notes, graph, and AI features rebuilt for touch — tabs, bottom sheets, and swipe-first interactions."},{"url":"https://memory.maria-code.ai/graph","title":"Knowledge Graph","description":"Explore the knowledge graph derived from [[wiki links]] in your notes — backlinks, clusters, and orphan detection with zero stored edges."},{"url":"https://memory.maria-code.ai/ask","title":"Ask — RAG over Your Vault","description":"Ask questions over your files with hybrid retrieval: vector + keyword search fused by RRF, with numbered citations back to sources."},{"url":"https://memory.maria-code.ai/ai","title":"AI Assistant","description":"Chat with an assistant grounded in your selected notes — local LLM (Ollama) or cloud, with sources cited in prose."},{"url":"https://memory.maria-code.ai/search","title":"Search","description":"Full-text and semantic search across the vault with CJK-aware tokenization and per-source filters."},{"url":"https://memory.maria-code.ai/research","title":"Research","description":"Multi-source research runs: web, papers, and vault sources gathered into citable findings."},{"url":"https://memory.maria-code.ai/agents","title":"Scheduled Agents","description":"Scheduled agents that synthesize, reconcile contradictions, heal orphans, and consolidate memory on cron schedules."},{"url":"https://memory.maria-code.ai/ingest","title":"Ingest","description":"Bring documents, web pages, and connector sources into the vault: chunking, embeddings, and content-hash dedup."},{"url":"https://memory.maria-code.ai/canvas","title":"Canvas","description":"A spatial canvas for arranging notes, cards, and connections visually."},{"url":"https://memory.maria-code.ai/daily","title":"Daily Notes","description":"Daily notes with task rollover, timeline view, and automatic linking into the knowledge graph."},{"url":"https://memory.maria-code.ai/bases","title":"Bases","description":"Database-style views over notes: tables, boards, and filters built from note properties."},{"url":"https://memory.maria-code.ai/bookmarks","title":"Bookmarks","description":"Saved notes, searches, and views pinned for fast access."},{"url":"https://memory.maria-code.ai/tags","title":"Tags","description":"The tag index derived from note frontmatter and inline tags across the vault."},{"url":"https://memory.maria-code.ai/templates","title":"Templates","description":"Reusable note templates for daily notes, meetings, research, and reviews."},{"url":"https://memory.maria-code.ai/health","title":"Vault Health","description":"Vault health metrics: orphan notes, unresolved links, stale claims, and contradiction queues."},{"url":"https://memory.maria-code.ai/avatar","title":"Realtime Avatar","description":"A realtime lip-synced avatar pipeline for voice conversations with your vault."},{"url":"https://memory.maria-code.ai/vault","title":"Local Vault","description":"Open a local folder as a Marian vault and edit Markdown and other files directly on your computer via the File System Access API."},{"url":"https://memory.maria-code.ai/vaults","title":"Vaults","description":"Manage multiple vaults: create, share, and switch between knowledge bases."},{"url":"https://memory.maria-code.ai/plugins","title":"Plugins","description":"Extend Marian with plugins: catalog, runtime events, and per-plugin settings."},{"url":"https://memory.maria-code.ai/publish","title":"Publish","description":"Publish selected notes as a public site with channels and deploy history."},{"url":"https://memory.maria-code.ai/attachments","title":"Attachments","description":"Files and attachments across the vault with previews and usage references."}],"blog":{"name":"Marian Engineering Blog","posts":[{"slug":"hybrid-retrieval-architecture","url":"https://memory.maria-code.ai/blog/hybrid-retrieval-architecture","title":"ハイブリッド検索の4段パイプライン — ACLフィルタ、バイナリ粗探索、int8リランク、RRF融合","excerpt":"MarianのAsk(RAG)は、ベクトル検索と全文検索を単純に混ぜていません。ACLフィルタ→バイナリ類似度による粗探索→int8ドット積によるリランク→Reciprocal Rank Fusionという4段パイプラインで、権限リークを構造的に防ぎながら複数の検索シグナルを統合します。本記事では各段の実装、RRFの式と定数(k=60、keyword重み0.85)、そしてフラグオフ時のグレースフルデグラデーション設計を解説します。","summary":"ハイブリッド検索の4段パイプライン — ACLフィルタ、バイナリ粗探索、int8リランク、RRF融合。MarianのAsk(RAG)は、ベクトル検索と全文検索を単純に混ぜていません。ACLフィルタ→バイナリ類似度による粗探索→int8ドット積によるリランク→Reciprocal Rank Fusionという4段パイプラインで、権限リークを構造的に防ぎながら複数の検索シグナルを統合します。本記事では各段の実装、RRFの式と定数(k=60、keyword重み0.85)、そしてフラグオフ時のグレースフルデグラデーション設計を解説します。 主要トピック: rag、hybrid-search、rrf、acl、vector-search、retrieval。要点: 検索はACLフィルタ→バイナリ粗探索(200件)→int8リランク(50件)→RRF融合(20件)の4段パイプライン。ACLはスコアリング前に述語適用するfail closed設計で、権限リークを構造的に排除する。RRFはk=60・keyword重み0.85/vector重み1.0で、スコア正規化なしに複数retrieverを統合する…","publishedAt":"2026-06-10","updatedAt":"2026-06-10","lang":"ja","category":"Search & Retrieval","categoryUrl":"https://memory.maria-code.ai/blog/category/search-retrieval","tags":[{"tag":"rag","url":"https://memory.maria-code.ai/blog/tag/rag"},{"tag":"hybrid-search","url":"https://memory.maria-code.ai/blog/tag/hybrid-search"},{"tag":"rrf","url":"https://memory.maria-code.ai/blog/tag/rrf"},{"tag":"acl","url":"https://memory.maria-code.ai/blog/tag/acl"},{"tag":"vector-search","url":"https://memory.maria-code.ai/blog/tag/vector-search"},{"tag":"retrieval","url":"https://memory.maria-code.ai/blog/tag/retrieval"}],"keyTakeaways":["検索はACLフィルタ→バイナリ粗探索(200件)→int8リランク(50件)→RRF融合(20件)の4段パイプライン","ACLはスコアリング前に述語適用するfail closed設計で、権限リークを構造的に排除する","RRFはk=60・keyword重み0.85/vector重み1.0で、スコア正規化なしに複数retrieverを統合する","前提が欠けると自動的に単純な方式へフォールバックし、フラグ有効化が常に安全"],"faq":[{"question":"なぜスコアの重み付き和ではなくRRF(Reciprocal Rank Fusion)を使うのか?","answer":"コサイン類似度とkeyword検索のスコアはスケールも分布も異なり、重み付き和は正規化のチューニングが必要になるためです。RRFは各retrieverの順位だけを使い、weight/(k+rank)を合算します(Marianはk=60、keyword重み0.85、vector重み1.0)。retrieverを追加しても順位リストを渡すだけで済みます。"},{"question":"マルチテナント環境での権限リークをどう防いでいるのか?","answer":"ACL述語(private/space/org/publicの4段階、デフォルト拒否)をスコアリング前に適用し、不可視IDは粗探索・リランク・融合のどのステージにも入らない設計です。「上位N件取得後にフィルタ」方式と違い、品質劣化もリークの余地も構造的に発生しません。"},{"question":"ASK_HYBRIDフラグを有効にして検索が壊れるリスクはないのか?","answer":"フォールバックチェーンがあるため壊れません。RAPTORツリーがなければ2段階量子化検索へ、バイナリ符号がなければ単段IVFFlat(fp32コサイン)へ自動で畳み込まれます。終端のIVFFlatは常に利用可能なので、フラグ有効化は安全な操作として設計されています。"}]},{"slug":"binary-quantization-pgvector","url":"https://memory.maria-code.ai/blog/binary-quantization-pgvector","title":"pgvectorで実装するバイナリ量子化 — 768次元を96バイトに圧縮する2段階検索","excerpt":"fp32の768次元埋め込みは1本3KB。コーパスが伸びるとメモリにもインデックスにも載らなくなります。Marianは符号1bit量子化(768次元→96バイト、32分の1)とHamming距離のHNSWインデックスで粗探索し、fp32コサインでリランクする2段階検索をpgvectorだけで実装しました。量子化の式、POPCOUNTテーブル、PostgreSQLのRPC、既存埋め込みからのゼロコストバックフィルまで、実装をそのまま解説します。","summary":"pgvectorで実装するバイナリ量子化 — 768次元を96バイトに圧縮する2段階検索。fp32の768次元埋め込みは1本3KB。コーパスが伸びるとメモリにもインデックスにも載らなくなります。Marianは符号1bit量子化(768次元→96バイト、32分の1)とHamming距離のHNSWインデックスで粗探索し、fp32コサインでリランクする2段階検索をpgvectorだけで実装しました。量子化の式、POPCOUNTテーブル、PostgreSQLのRPC、既存埋め込みからのゼロコストバックフィルまで、実装をそのまま解説します。 主要トピック: quantization、pgvector、hnsw、hamming-distance、embeddings、postgres。要点: 符号1bit量子化で768次元fp32(3KB)を96バイトに圧縮し、Hamming距離で粗探索する。精度は2段階設計で取り戻す: バイナリで200件→fp32コサインでリランク。pgvectorのbit(768)+HNSW bit_hamming_opsだけで実装でき、専用ベクトルDBは不要。バイナリ列は既存fp32からSQLで導出でき…","publishedAt":"2026-06-08","updatedAt":"2026-06-08","lang":"ja","category":"Search & Retrieval","categoryUrl":"https://memory.maria-code.ai/blog/category/search-retrieval","tags":[{"tag":"quantization","url":"https://memory.maria-code.ai/blog/tag/quantization"},{"tag":"pgvector","url":"https://memory.maria-code.ai/blog/tag/pgvector"},{"tag":"hnsw","url":"https://memory.maria-code.ai/blog/tag/hnsw"},{"tag":"hamming-distance","url":"https://memory.maria-code.ai/blog/tag/hamming-distance"},{"tag":"embeddings","url":"https://memory.maria-code.ai/blog/tag/embeddings"},{"tag":"postgres","url":"https://memory.maria-code.ai/blog/tag/postgres"}],"keyTakeaways":["符号1bit量子化で768次元fp32(3KB)を96バイトに圧縮し、Hamming距離で粗探索する","精度は2段階設計で取り戻す: バイナリで200件→fp32コサインでリランク","pgvectorのbit(768)+HNSW bit_hamming_opsだけで実装でき、専用ベクトルDBは不要","バイナリ列は既存fp32からSQLで導出でき、再埋め込みコストゼロ・冪等にバックフィルできる"],"faq":[{"question":"1bit量子化でなぜ検索精度が保てるのか?","answer":"高次元埋め込みではコサイン類似度と符号一致率に強い相関があるためです(ランダム超平面LSHと同じ原理)。さらにMarianは粗探索でしかバイナリを使わず、上位200件をfp32コサインでリランクするため、最終順位の精度はfp32側が保証します。"},{"question":"既存の埋め込みデータへのバイナリ列追加にコストはかかるのか?","answer":"かかりません。fp32埋め込みがDBに保存済みなので、unnest+string_aggのSQLで符号からビット文字列を導出するだけです。LLM APIの再呼び出しはゼロで、WHERE embedding_binary IS NULLにより冪等に実行できます。"},{"question":"なぜ専用のベクトルDB(Faiss、Qdrant等)を使わないのか?","answer":"pgvectorのbit型+HNSW(bit_hamming_ops)で2段階検索が実装でき、データ・ACL・トランザクションをPostgreSQL一箇所に保てるためです。RPC関数1つで粗探索→リランクが完結し、運用するシステムが増えません。規模がさらに伸びた場合の専用エンジン移行も、量子化層が純粋関数なので差し替え可能です。"}]},{"slug":"raptor-hierarchical-rag","url":"https://memory.maria-code.ai/blog/raptor-hierarchical-rag","title":"RAPTOR要約ツリーの実装 — バイナリ重心クラスタリングとcollapsed-tree検索","excerpt":"チャンク単位のRAGは「このドキュメント群は全体として何を言っているか」という広い質問に弱い。MarianはRAPTOR(Recursive Abstractive Processing for Tree-Organized Retrieval)方式の要約ツリーを実装し、リーフ(チャンク)から要約ノードを再帰的に積み上げます。本記事では、葉数加重のバイナリ重心、貪欲最近傍クラスタリング(branching=4)、全階層を一括スコアリングするcollapsed-tree検索、そしてmarian_file_tree_nodesテーブルへの永続化を解説します。","summary":"RAPTOR要約ツリーの実装 — バイナリ重心クラスタリングとcollapsed-tree検索。チャンク単位のRAGは「このドキュメント群は全体として何を言っているか」という広い質問に弱い。MarianはRAPTOR(Recursive Abstractive Processing for Tree-Organized Retrieval)方式の要約ツリーを実装し、リーフ(チャンク)から要約ノードを再帰的に積み上げます。本記事では、葉数加重のバイナリ重心、貪欲最近傍クラスタリング(branching=4)、全階層を一括スコアリングするcollapsed-tree検索、そしてmarian_file_tree_nodesテーブルへの永続化を解説します。 主要トピック: raptor、rag、hierarchical-retrieval、clustering、summarization、postgres。要点: RAPTORツリーで「複数チャンクにまたがる抽象的な質問」に答えられるようにする。親ノードの重心は配下リーフ数で重み付けしたビット多数決で、小さい枝への偏りを防ぐ…","publishedAt":"2026-06-05","updatedAt":"2026-06-05","lang":"ja","category":"Search & Retrieval","categoryUrl":"https://memory.maria-code.ai/blog/category/search-retrieval","tags":[{"tag":"raptor","url":"https://memory.maria-code.ai/blog/tag/raptor"},{"tag":"rag","url":"https://memory.maria-code.ai/blog/tag/rag"},{"tag":"hierarchical-retrieval","url":"https://memory.maria-code.ai/blog/tag/hierarchical-retrieval"},{"tag":"clustering","url":"https://memory.maria-code.ai/blog/tag/clustering"},{"tag":"summarization","url":"https://memory.maria-code.ai/blog/tag/summarization"},{"tag":"postgres","url":"https://memory.maria-code.ai/blog/tag/postgres"}],"keyTakeaways":["RAPTORツリーで「複数チャンクにまたがる抽象的な質問」に答えられるようにする","親ノードの重心は配下リーフ数で重み付けしたビット多数決で、小さい枝への偏りを防ぐ","クラスタリングは貪欲最近傍(branching=4)で決定的。品質はリランクで吸収する割り切り","検索はcollapsed-tree方式で全階層を一括スコアリングし、トラバーサル設計を不要にする","LLM要約は注入分離されており、ツリー構築・検索はLLMなしで完結する"],"faq":[{"question":"RAPTORは通常のチャンクRAGと何が違うのか?","answer":"チャンクRAGは特定の段落に答えがある質問にしか強くありません。RAPTORはチャンクをクラスタリングして要約を再帰的に積み上げ、抽象度の階層を作ります。具体的な質問はリーフに、「全体として何を言っているか」のような広い質問は上位の要約ノードにヒットします。"},{"question":"なぜ検索時にツリーを上から辿らず、全ノードを一括スコアリングするのか?","answer":"貪欲に降りる方式は上位階層での判断ミスから回復できないためです。collapsed-tree方式は全階層のノードを同じ土俵でスコアリングし、質問の抽象度に合った階層のノードが自然に上位に来ます。トラバーサルポリシーの設計自体が不要になります。"},{"question":"LLMによる要約生成が失敗したらツリーは使えなくなるのか?","answer":"使えます。要約はsummarizeコールバックとして任意注入する設計で、ツリーの構築と検索はバイナリ重心とリーフ数だけで機能します。要約文は後から非同期に埋められるため、LLM障害がインデックス構築をブロックしません。"}]},{"slug":"ingest-pipeline-content-hash","url":"https://memory.maria-code.ai/blog/ingest-pipeline-content-hash","title":"インジェストパイプラインとcontent-hashキャッシュ — 再インデックスを差分だけにする","excerpt":"ドキュメントをRAGに載せる経路は「分割→埋め込み→格納」の3手に見えますが、運用で効くのは2回目以降の再インデックスです。Marianはチャンク内容のFNV-1aデュアルハッシュをembeddingsテーブルに併置し、変更のないチャンクの再埋め込みをスキップします。チャンクサイズの実定数(1400字/256トークン)、ファイル種別ごとの分割戦略、planReindexによる差分計画の実装を解説します。","summary":"インジェストパイプラインとcontent-hashキャッシュ — 再インデックスを差分だけにする。ドキュメントをRAGに載せる経路は「分割→埋め込み→格納」の3手に見えますが、運用で効くのは2回目以降の再インデックスです。Marianはチャンク内容のFNV-1aデュアルハッシュをembeddingsテーブルに併置し、変更のないチャンクの再埋め込みをスキップします。チャンクサイズの実定数(1400字/256トークン)、ファイル種別ごとの分割戦略、planReindexによる差分計画の実装を解説します。 主要トピック: ingest、chunking、embeddings、content-hash、dedup、rag。要点: 再インデックスが支配的ワークロード。分割は毎回・埋め込みは差分だけという非対称設計にする。チャンクはファイル種別の構造(見出し/定義/段落/文)で分割し、file summaryチャンクでメタデータも検索可能にする。FNV-1aデュアルハッシュ(実効64bit)+planReindexで、変更のないチャンクの再埋め込みをゼロにする…","publishedAt":"2026-06-02","updatedAt":"2026-06-02","lang":"ja","category":"Engineering","categoryUrl":"https://memory.maria-code.ai/blog/category/engineering","tags":[{"tag":"ingest","url":"https://memory.maria-code.ai/blog/tag/ingest"},{"tag":"chunking","url":"https://memory.maria-code.ai/blog/tag/chunking"},{"tag":"embeddings","url":"https://memory.maria-code.ai/blog/tag/embeddings"},{"tag":"content-hash","url":"https://memory.maria-code.ai/blog/tag/content-hash"},{"tag":"dedup","url":"https://memory.maria-code.ai/blog/tag/dedup"},{"tag":"rag","url":"https://memory.maria-code.ai/blog/tag/rag"}],"keyTakeaways":["再インデックスが支配的ワークロード。分割は毎回・埋め込みは差分だけという非対称設計にする","チャンクはファイル種別の構造(見出し/定義/段落/文)で分割し、file summaryチャンクでメタデータも検索可能にする","FNV-1aデュアルハッシュ(実効64bit)+planReindexで、変更のないチャンクの再埋め込みをゼロにする","重複排除はアプリロジックでなくハッシュ+DBユニーク制約としてデータ層に沈める"],"faq":[{"question":"content-hashにSHA-256ではなくFNV-1aを使うのはなぜか?","answer":"目的が改ざん耐性ではなく「同じ内容を二度埋め込まない」ことだからです。シードの異なるFNV-1a 32bitを2本連結して実効64bitにすれば衝突確率は実用上十分小さく、同期的な純粋関数のまま保てるためテストも容易です。Web Crypto APIの非同期化も避けられます。"},{"question":"ファイルを少し編集したとき、何が再埋め込みされるのか?","answer":"planReindexが保存済みチャンクのハッシュと新チャンクのハッシュを突き合わせ、新規ハッシュのチャンクだけをtoEmbedに、消えたハッシュの行をtoDeleteに入れます。変更のない段落のチャンクはハッシュが一致するため埋め込みAPIに送られません。ファイル全体が無変更ならDB書き込み自体が発生しません。"},{"question":"チャンクサイズはどう決まっているのか?","answer":"段落ベースで上限1,200字(目標1,400字)、トークンベースのブロック分割では256トークンです。固定長で切らず、Markdownは見出し、コードは定義境界、テキストは段落→文の順にフォールバックして意味の境界を保ちます。1ファイルの本文チャンクは5個までに制限し、先頭にメタデータを詰めたfile summaryチャンクを置きます。"}]},{"slug":"postgres-job-queue","url":"https://memory.maria-code.ai/blog/postgres-job-queue","title":"Postgresだけで作るジョブキュー — リース、冪等キー、指数バックオフの実装","excerpt":"埋め込み生成や音声転写のような長時間ジョブをWebリクエストの中で実行はできません。MarianはRedisもSQSも足さず、Postgresのテーブル1枚でジョブキューを実装しました。状態機械(queued→running→retrying→succeeded/dead)、30秒リースによるクラッシュ回復、部分ユニークインデックスによる冪等性、1s→5分capの指数バックオフまで、スキーマと実装をそのまま解説します。","summary":"Postgresだけで作るジョブキュー — リース、冪等キー、指数バックオフの実装。埋め込み生成や音声転写のような長時間ジョブをWebリクエストの中で実行はできません。MarianはRedisもSQSも足さず、Postgresのテーブル1枚でジョブキューを実装しました。状態機械(queued→running→retrying→succeeded/dead)、30秒リースによるクラッシュ回復、部分ユニークインデックスによる冪等性、1s→5分capの指数バックオフまで、スキーマと実装をそのまま解説します。 主要トピック: job-queue、postgres、supabase、idempotency、backoff、async。要点: Postgresテーブル1枚+インデックス4本で冪等投入・優先度クレーム・クラッシュ回復・バックオフ・デッドレターを実装できる。冪等性は部分ユニークインデックス(where status <> dead)でDB層に沈め、dead後の再投入も両立する。クラッシュ回復はリース方式(30秒)で、ロックもハートビートも不要。バックオフはrun_afterを未来に置くだけ(1s→2倍→5分cap)…","publishedAt":"2026-05-30","updatedAt":"2026-05-30","lang":"ja","category":"Engineering","categoryUrl":"https://memory.maria-code.ai/blog/category/engineering","tags":[{"tag":"job-queue","url":"https://memory.maria-code.ai/blog/tag/job-queue"},{"tag":"postgres","url":"https://memory.maria-code.ai/blog/tag/postgres"},{"tag":"supabase","url":"https://memory.maria-code.ai/blog/tag/supabase"},{"tag":"idempotency","url":"https://memory.maria-code.ai/blog/tag/idempotency"},{"tag":"backoff","url":"https://memory.maria-code.ai/blog/tag/backoff"},{"tag":"async","url":"https://memory.maria-code.ai/blog/tag/async"}],"keyTakeaways":["Postgresテーブル1枚+インデックス4本で冪等投入・優先度クレーム・クラッシュ回復・バックオフ・デッドレターを実装できる","冪等性は部分ユニークインデックス(where status <> dead)でDB層に沈め、dead後の再投入も両立する","クラッシュ回復はリース方式(30秒)で、ロックもハートビートも不要","バックオフはrun_afterを未来に置くだけ(1s→2倍→5分cap)。スケジューリングの語彙が1つに統一される","状態遷移は時刻を引数に取る純粋関数で、DBなしでテストできる"],"faq":[{"question":"RedisやSQSではなくPostgresでジョブキューを作る理由は?","answer":"ジョブが参照するデータと同じDBにキューがあるとトランザクション整合性が自然に手に入り、運用するインフラも増えないためです。Marianのワークロードはユーザー操作起点のバースト(数十〜数百件)が中心で、Postgresキューのスループット上限が問題になりません。状態機械は純粋関数として分離してあるため、規模が変わればストアだけ差し替えられます。"},{"question":"ワーカーがクラッシュしたジョブはどう回復されるのか?","answer":"リース(可視性タイムアウト)方式です。claim時にlease_untilを30秒先に設定し、完了しないままリースが切れた running ジョブは reclaimExpired が retrying に戻します。分散ロックやハートビートは不要で、(status, lease_until)のインデックスを見るだけで回収できます。"},{"question":"同じジョブの二重投入はどう防いでいるのか?","answer":"idempotency_keyの部分ユニークインデックス(where status <> dead)で防ぎます。アクティブな同キージョブがある間の再投入は既存ジョブにdedupされ、デッドレター化後は同じキーで再投入できます。アプリのチェックではなくDB制約なので、並行実行でも破れません。"}]},{"slug":"agent-memory-episodes","url":"https://memory.maria-code.ai/blog/agent-memory-episodes","title":"エージェントメモリの設計 — 7軸サリエンス、半減期減衰、エピソードからポリシーへ","excerpt":"「全部覚える」エージェントメモリは検索ノイズと化します。Marianのメモリ基盤は、7軸のサリエンス(重要度・リスク・緊急度など)で記憶をスコアリングし、夜間ジョブで短期→長期へ昇格(consolidation)、軸ごとの半減期で減衰させて抽象度を引き上げる(distillation)、という生体記憶に似た2つのプロセスで管理します。エピソードDBスキーマ、合成サリエンスの重み、キュー索引によるO(最小ポスティングリスト)のリコールまで実装を解説します。","summary":"エージェントメモリの設計 — 7軸サリエンス、半減期減衰、エピソードからポリシーへ。「全部覚える」エージェントメモリは検索ノイズと化します。Marianのメモリ基盤は、7軸のサリエンス(重要度・リスク・緊急度など)で記憶をスコアリングし、夜間ジョブで短期→長期へ昇格(consolidation)、軸ごとの半減期で減衰させて抽象度を引き上げる(distillation)、という生体記憶に似た2つのプロセスで管理します。エピソードDBスキーマ、合成サリエンスの重み、キュー索引によるO(最小ポスティングリスト)のリコールまで実装を解説します。 主要トピック: agent-memory、episodic-memory、salience、memory-consolidation、ai-agents。要点: 記憶システムの本体は書き込みではなく価値の経時管理(サリエンス・昇格・忘却)。7軸サリエンスは軸ごとに半減期が異なり(urgency 7日〜sensitivity 365日)、時間構造を表現する。consolidationは「2回繰り返した」または「一度でもsalience 0.8以上」で短期→長期へ昇格させる…","publishedAt":"2026-05-27","updatedAt":"2026-05-27","lang":"ja","category":"AI & Agents","categoryUrl":"https://memory.maria-code.ai/blog/category/ai-agents","tags":[{"tag":"agent-memory","url":"https://memory.maria-code.ai/blog/tag/agent-memory"},{"tag":"episodic-memory","url":"https://memory.maria-code.ai/blog/tag/episodic-memory"},{"tag":"salience","url":"https://memory.maria-code.ai/blog/tag/salience"},{"tag":"memory-consolidation","url":"https://memory.maria-code.ai/blog/tag/memory-consolidation"},{"tag":"ai-agents","url":"https://memory.maria-code.ai/blog/tag/ai-agents"}],"keyTakeaways":["記憶システムの本体は書き込みではなく価値の経時管理(サリエンス・昇格・忘却)","7軸サリエンスは軸ごとに半減期が異なり(urgency 7日〜sensitivity 365日)、時間構造を表現する","consolidationは「2回繰り返した」または「一度でもsalience 0.8以上」で短期→長期へ昇格させる","distillationは削除せず抽象度を上げる忘却。原本はprovenanceとして残る","全判定が時刻を引数に取る純粋関数で、記憶のライフサイクルをユニットテストできる"],"faq":[{"question":"なぜ記憶のスコアを単一の数値ではなく7軸で持つのか?","answer":"減衰速度が軸ごとに違うからです。緊急度は半減期7日で消えるべきですが、重要度とリスクは180日残すべきです。単一スコアではこの時間構造を表現できません。合成が必要な場面ではcompositeSalience(重み付き和×confidenceゲート)に畳み、リスクまたは重要度0.7以上は忘却から保護します。"},{"question":"記憶が増えても想起が遅くならないのはなぜか?","answer":"actor・time・outcome・typeの各次元に転置インデックス(ポスティングリスト)を持ち、最も選択的なキューのリストを起点に積集合を取るためです。実際に調べる件数は最小ポスティングリスト長に比例し、総エピソード数Nには依存しません。pruneはexaminedとfullScanのコストを返すので、効率の回帰テストも可能です。"},{"question":"古い記憶は削除されるのか?","answer":"削除されません。週次のdistillationジョブが半減期減衰後のサリエンスが床値(0.35)を下回った記憶をraw→summary→pattern→principle→policyの抽象度ラダーで1段引き上げ、原本は来歴として保持します。検索の前面には抽象化された記憶が出て、詳細が必要なときだけ原本に降りられます。"}]},{"slug":"envelope-protocol-multi-agent","url":"https://memory.maria-code.ai/blog/envelope-protocol-multi-agent","title":"エージェントAPIに「責任境界」を埋め込む — エンベロープ・プロトコルの設計","excerpt":"マルチエージェントシステムの障害調査は「どのエージェントが、何の権限で、どのリクエストを処理したか」が分からないと始まりません。Marianは全APIルートをエンベロープ(封筒)契約で包み、trace ID・発信元・宛先・座標・ケイパビリティをメタデータとして強制します。さらに各エージェントは「禁止/回避/提案のみ/再確認/許可」の5段階責任境界を宣言し、ルート実装はevaluate()で判定を受け取ります。wire format、座標系、静的検証ハーネスまで解説します。","summary":"エージェントAPIに「責任境界」を埋め込む — エンベロープ・プロトコルの設計。マルチエージェントシステムの障害調査は「どのエージェントが、何の権限で、どのリクエストを処理したか」が分からないと始まりません。Marianは全APIルートをエンベロープ(封筒)契約で包み、trace ID・発信元・宛先・座標・ケイパビリティをメタデータとして強制します。さらに各エージェントは「禁止/回避/提案のみ/再確認/許可」の5段階責任境界を宣言し、ルート実装はevaluate()で判定を受け取ります。wire format、座標系、静的検証ハーネスまで解説します。 主要トピック: multi-agent、agent-protocol、governance、api-design、observability。要点: 全API入出力を共通メタデータ付きの封筒で包み、trace・発信元・権限を構造的に強制する。G.U.P.Z.A形式の座標がエージェントの住所になり、集計・ポリシー適用の単位として機能する。責任境界はblocked/avoid/suggest_only/reconfirm/allowedの5段階で、can と should…","publishedAt":"2026-05-24","updatedAt":"2026-05-24","lang":"ja","category":"AI & Agents","categoryUrl":"https://memory.maria-code.ai/blog/category/ai-agents","tags":[{"tag":"multi-agent","url":"https://memory.maria-code.ai/blog/tag/multi-agent"},{"tag":"agent-protocol","url":"https://memory.maria-code.ai/blog/tag/agent-protocol"},{"tag":"governance","url":"https://memory.maria-code.ai/blog/tag/governance"},{"tag":"api-design","url":"https://memory.maria-code.ai/blog/tag/api-design"},{"tag":"observability","url":"https://memory.maria-code.ai/blog/tag/observability"}],"keyTakeaways":["全API入出力を共通メタデータ付きの封筒で包み、trace・発信元・権限を構造的に強制する","G.U.P.Z.A形式の座標がエージェントの住所になり、集計・ポリシー適用の単位として機能する","責任境界はblocked/avoid/suggest_only/reconfirm/allowedの5段階で、can と should のずれを表現する","規約はレジストリ+withEnvelopeアダプタ+静的ハーネスの3点セットで機械的に守らせる","生JSONも受け付ける後方互換(受信は寛容に、送信は厳格に)で段階移行する"],"faq":[{"question":"エンベロープ・プロトコルは何を解決するのか?","answer":"マルチエージェント環境での(1)リクエスト連鎖を貫通するtrace、(2)発信元・宛先・権限の標準語彙、(3)エージェントごとの責任境界の宣言場所、の3つの欠落を解決します。全APIの入出力がprotocol/id/traceId/source/target/coordinate/capabilityを持つ封筒で包まれ、拒否応答もboundary付きの構造化データとして返ります。"},{"question":"なぜ権限を許可/禁止の2値ではなく5段階にするのか?","answer":"エージェントの行動には「技術的には可能だが姿勢として避ける(avoid)」「起案はするが決定は人間(suggest_only)」「実行前に平易な言葉で再確認(reconfirm)」というグレーゾーンが本質的に存在するためです。2値ではこれらをすべてblockedに倒すか、危険を許可するかの二択になります。5段階なら判定ロジックが優先順位つきの決定木として実装できます。"},{"question":"ストリーミング応答でもエンベロープは維持されるのか?","answer":"維持されます。withEnvelopeStreamがボディ(SSE/NDJSON)はそのまま流し、封筒メタデータをx-marian-trace、x-marian-coordinate、x-marian-capabilityヘッダに載せます。ストリーム開始前に起きたエラーのみ通常のJSON封筒で返すため、「全応答が封筒情報を持つ」という不変条件が保たれます。"}]},{"slug":"local-llm-routing","url":"https://memory.maria-code.ai/blog/local-llm-routing","title":"ローカルLLMとクラウドLLMを同じ土俵に載せる — プロバイダ抽象化とブートストラップ設計","excerpt":"プライバシー重視のユーザーはローカルLLM(Ollama)を、品質重視のユーザーはクラウドを選びます。Marianのチャット基盤は provider パラメータ1つでOllama・OpenAI互換サーバー・Geminiを切り替え、NDJSONとSSEという異なるストリーミング形式を共通のチャンク列へ正規化します。さらに「Ollama未インストール」から「モデル取得済み」までを導く決定的ステートマシンのブートストラップウィザード(I/Oゼロの純粋関数)を実装しました。その設計を解説します。","summary":"ローカルLLMとクラウドLLMを同じ土俵に載せる — プロバイダ抽象化とブートストラップ設計。プライバシー重視のユーザーはローカルLLM(Ollama)を、品質重視のユーザーはクラウドを選びます。Marianのチャット基盤は provider パラメータ1つでOllama・OpenAI互換サーバー・Geminiを切り替え、NDJSONとSSEという異なるストリーミング形式を共通のチャンク列へ正規化します。さらに「Ollama未インストール」から「モデル取得済み」までを導く決定的ステートマシンのブートストラップウィザード(I/Oゼロの純粋関数)を実装しました。その設計を解説します。 主要トピック: local-llm、ollama、streaming、provider-abstraction、gemini、llm-routing。要点: プロバイダ抽象化の主戦場はモデルではなくストリーミング形式(NDJSON vs SSE)の正規化。プロンプト構築・コンテキスト上限・中断処理は共通化し、プロバイダで変えるのは輸送だけ。デフォルトをローカル(Ollama)にし、プライベートなノートを外部に送らない選択を一級市民にする…","publishedAt":"2026-05-22","updatedAt":"2026-05-22","lang":"ja","category":"AI & Agents","categoryUrl":"https://memory.maria-code.ai/blog/category/ai-agents","tags":[{"tag":"local-llm","url":"https://memory.maria-code.ai/blog/tag/local-llm"},{"tag":"ollama","url":"https://memory.maria-code.ai/blog/tag/ollama"},{"tag":"streaming","url":"https://memory.maria-code.ai/blog/tag/streaming"},{"tag":"provider-abstraction","url":"https://memory.maria-code.ai/blog/tag/provider-abstraction"},{"tag":"gemini","url":"https://memory.maria-code.ai/blog/tag/gemini"},{"tag":"llm-routing","url":"https://memory.maria-code.ai/blog/tag/llm-routing"}],"keyTakeaways":["プロバイダ抽象化の主戦場はモデルではなくストリーミング形式(NDJSON vs SSE)の正規化","プロンプト構築・コンテキスト上限・中断処理は共通化し、プロバイダで変えるのは輸送だけ","デフォルトをローカル(Ollama)にし、プライベートなノートを外部に送らない選択を一級市民にする","セットアップウィザードは「状態→次の1手」の純粋関数として書き、UIから分岐ロジックを排除する"],"faq":[{"question":"ローカルLLMとクラウドLLMの切り替えはどう実装されているのか?","answer":"チャットAPIのリクエストボディにproviderフィールド(ollama / openai-compatible、デフォルトはollama)を持たせ、ルート内で対応するストリーム関数に分岐します。エンドポイントとモデルは環境変数(OLLAMA_BASE_URL、OPENAI_COMPATIBLE_BASE_URL等)で上書きでき、プロンプト構築・コンテキスト刈り込み・中断処理は全プロバイダ共通です。"},{"question":"OllamaとOpenAI互換APIのストリーミング形式の違いはどう吸収するのか?","answer":"OllamaはNDJSON({message:{content}}の行)、OpenAI互換はSSE(data: {choices:[{delta:{content}}]}、終端[DONE])という違いを、各stream関数がパースして「テキストチャンクの列」という同一契約に正規化します。呼び出し側はどちらのプロバイダでも同じコードでチャンクを消費できます。"},{"question":"Ollamaが未インストールのユーザーはどう扱われるのか?","answer":"ブートストラップウィザードが4つの真偽値(インストール済み/サーバー到達可能/チャットモデル有/埋め込みモデル有)の状態から次の1手(install / start / pull-models / done / use-cloud)を返します。OS別のインストールガイドとモデルpullの進捗表示つきで誘導し、ローカルを拒否した場合はクラウドにフォールバックします。この判定はI/Oゼロの純粋関数で全分岐がテスト済みです。"}]},{"slug":"context-engine-token-budget","url":"https://memory.maria-code.ai/blog/context-engine-token-budget","title":"コンテキストエンジンの設計 — スコープ×グレイン×トークン予算で「何をLLMに見せるか」を計画する","excerpt":"RAGの「どのドキュメントをどの粒度でプロンプトに入れるか」は、普通ユーザーから見えないブラックボックスです。Marianのコンテキストエンジンはこれを明示的なデータ構造にしました。スコープ(notebook/vault)×ソースごとのグレイン(full/summary/excluded)の組み合わせからトークン見積もりつきのContextPlanを構築し、8,000トークンのソフト予算に対する消費をユーザーに見せます。計画と実行を分離するこの設計は、要約プランナー(single vs map-reduce)にも貫かれています。","summary":"コンテキストエンジンの設計 — スコープ×グレイン×トークン予算で「何をLLMに見せるか」を計画する。RAGの「どのドキュメントをどの粒度でプロンプトに入れるか」は、普通ユーザーから見えないブラックボックスです。Marianのコンテキストエンジンはこれを明示的なデータ構造にしました。スコープ(notebook/vault)×ソースごとのグレイン(full/summary/excluded)の組み合わせからトークン見積もりつきのContextPlanを構築し、8,000トークンのソフト予算に対する消費をユーザーに見せます。計画と実行を分離するこの設計は、要約プランナー(single vs map-reduce)にも貫かれています。 主要トピック: context-engineering、token-budget、rag、summarization、prompt-engineering。要点: コンテキスト選択を暗黙のtop-kからスコープ×グレインの明示的なデータ構造に変える。デフォルト(ノートブック内=full、リンク近傍=summary)でユーザー意図の強さとトークン消費を比例させる。見積もりは4文字=1トークンで十分…","publishedAt":"2026-05-20","updatedAt":"2026-05-20","lang":"ja","category":"Architecture","categoryUrl":"https://memory.maria-code.ai/blog/category/architecture","tags":[{"tag":"context-engineering","url":"https://memory.maria-code.ai/blog/tag/context-engineering"},{"tag":"token-budget","url":"https://memory.maria-code.ai/blog/tag/token-budget"},{"tag":"rag","url":"https://memory.maria-code.ai/blog/tag/rag"},{"tag":"summarization","url":"https://memory.maria-code.ai/blog/tag/summarization"},{"tag":"prompt-engineering","url":"https://memory.maria-code.ai/blog/tag/prompt-engineering"}],"keyTakeaways":["コンテキスト選択を暗黙のtop-kからスコープ×グレインの明示的なデータ構造に変える","デフォルト(ノートブック内=full、リンク近傍=summary)でユーザー意図の強さとトークン消費を比例させる","見積もりは4文字=1トークンで十分。精度の要件は用途(判断支援)が決める","計画と実行の分離(ContextPlan / SummaryPlan / ReindexPlan)はテスト・可観測性・キャンセル安全性を同時に買う"],"faq":[{"question":"コンテキストエンジンのスコープとグレインとは何か?","answer":"スコープはコンテキスト候補の範囲で、notebook(選択したソースのみ)とvault(ソースからリンクされた近傍ノートも候補に含む)の2種類。グレインはソースごとの粒度で、full(全文)/summary(要約)/excluded(除外)の3段階です。この直積からトークン見積もりつきのContextPlanが構築されます。"},{"question":"トークン見積もりはなぜ正確なトークナイザを使わないのか?","answer":"用途が課金や強制切り詰めではなく、ユーザーの意思決定支援(このノートを全文で入れると予算の何%か)だからです。4文字=1トークンの近似で±20%程度の誤差は判断に影響せず、依存ライブラリなしの同期計算という性質の方が価値があります。予算8,000トークンもソフトリミットで、超過は警告として表示されます。"},{"question":"長文の要約はどう計画されるのか?","answer":"要約プランナーが入力トークン数(4文字=1トークン見積もり)とコンテキストウィンドウ(既定8,000、予約1,500)を比較し、収まればsingle、収まらなければmap-reduce戦略を選びます。map段の各チャンクには最終目標トークン(short=80/medium=250/long=700)の約60%を割り当て、チャンク分割は文字レンジとして計画に含まれます。LLMを呼ばずに計画が確定するためテスト可能です。"}]},{"slug":"rag-eval-harness","url":"https://memory.maria-code.ai/blog/rag-eval-harness","title":"RAG評価をCIに入れる — 決定的シンセティックコーパスとrecall@kゲート","excerpt":"検索パイプラインに量子化やRAPTORのような変更を入れるとき、「壊れていないこと」をどう保証するか。LLM-as-a-judgeは遅く高くフレーキーで、CIゲートには不向きです。Marianはシード固定のシンセティックコーパス(24トピック×10チャンク、120クエリ)に対してrecall@k / MRR / nDCG / MAPを計算し、recall@10 >= 0.6を満たさなければCIを落とす決定的な評価ハーネスを実装しました。指標の実装からコーパス生成、ゲート設計までを解説します。","summary":"RAG評価をCIに入れる — 決定的シンセティックコーパスとrecall@kゲート。検索パイプラインに量子化やRAPTORのような変更を入れるとき、「壊れていないこと」をどう保証するか。LLM-as-a-judgeは遅く高くフレーキーで、CIゲートには不向きです。Marianはシード固定のシンセティックコーパス(24トピック×10チャンク、120クエリ)に対してrecall@k / MRR / nDCG / MAPを計算し、recall@10 >= 0.6を満たさなければCIを落とす決定的な評価ハーネスを実装しました。指標の実装からコーパス生成、ゲート設計までを解説します。 主要トピック: evaluation、rag、recall、ndcg、ci、testing、information-retrieval。要点: 検索品質の回帰は型エラーにならない。CIに決定的な評価ゲートを置くことがretrieval層の変更可能性を守る。評価対象を検索に絞ればLLM不要。recall@k / MRR / nDCG / MAP / precisionの並列出力で劣化の方向が見える…","publishedAt":"2026-05-19","updatedAt":"2026-05-19","lang":"ja","category":"Engineering","categoryUrl":"https://memory.maria-code.ai/blog/category/engineering","tags":[{"tag":"evaluation","url":"https://memory.maria-code.ai/blog/tag/evaluation"},{"tag":"rag","url":"https://memory.maria-code.ai/blog/tag/rag"},{"tag":"recall","url":"https://memory.maria-code.ai/blog/tag/recall"},{"tag":"ndcg","url":"https://memory.maria-code.ai/blog/tag/ndcg"},{"tag":"ci","url":"https://memory.maria-code.ai/blog/tag/ci"},{"tag":"testing","url":"https://memory.maria-code.ai/blog/tag/testing"},{"tag":"information-retrieval","url":"https://memory.maria-code.ai/blog/tag/information-retrieval"}],"keyTakeaways":["検索品質の回帰は型エラーにならない。CIに決定的な評価ゲートを置くことがretrieval層の変更可能性を守る","評価対象を検索に絞ればLLM不要。recall@k / MRR / nDCG / MAP / precisionの並列出力で劣化の方向が見える","シード固定のシンセティックコーパスは絶対品質でなく差分検出のための道具","CIゲートはrecall@10 >= 0.6の1条件のみ。多条件ゲートは形骸化を招く","retrieve関数を差し込む設計で、単段/2段階/RAPTORを同じ物差しで比較できる"],"faq":[{"question":"なぜLLM-as-a-judgeをCIゲートに使わないのか?","answer":"遅い(分単位)・高い(毎実行課金)・非決定的(同じコードで通ったり落ちたり)という3点でCIゲートに不適だからです。RAGの障害の大半は検索層の劣化なので、検索だけを古典的IR指標(recall@k等)で決定的に評価すれば、数秒・無料・再現可能なゲートになります。生成品質の評価はステージングでの手動評価に分離しています。"},{"question":"シンセティックコーパスで実際の検索品質が保証できるのか?","answer":"絶対品質は保証できません。保証するのは「変更前後の差分」です。シード固定(mulberry32, seed=42)の24トピック×240チャンク×120クエリに対するスコア変動は、コード変更だけを反映します。量子化の符号ミスやRRF融合のバグのような検索アルゴリズム層の回帰はこれで検出でき、語彙の曖昧性など実データ固有の難しさは守備範囲外と割り切っています。"},{"question":"CIのしきい値がrecall@10だけなのはなぜか?","answer":"RAGではコンテキストに入らなかった正解は存在しないのと同じであり、recallが最も直接的な品質指標だからです。複数指標をゲートにすると自然な揺らぎでCIが落ち、赤いCIが常態化して形骸化します。MRR・nDCG・MAP・precisionはレポートに出して人間のレビュー判断に使い、機械的な強制はrecall@10 >= 0.6の1条件に絞っています。"}]}]}}