Initial SOC memory POC implementation

This commit is contained in:
2026-04-27 17:13:06 +08:00
parent fc68581198
commit e6b1520bce
89 changed files with 7610 additions and 1 deletions

View File

@ -0,0 +1,36 @@
# commit_memory_skill
这个 skill 负责把标准化后的高价值记忆写回 OpenViking。
## 当前阶段职责
第一阶段优先把标准化后的 `case``knowledge` 以 resource 形式写入 OpenViking。
原因:
- 结构化数据适合用 URI 明确组织
- 相比通过会话提交 `add_memory`resource 写入更可控
- 便于后续按 namespace 和 URI 组织 case / knowledge / report
## 第一阶段输入
- 标准化后的 case JSON
- 标准化后的 KB / Playbook JSON
## 第一阶段输出
- OpenViking resource 写入结果
- 统一 URI 组织的资源
## 默认 URI 约定
- case: `viking://soc/case/<scenario>/<id>`
- knowledge: `viking://soc/knowledge/<doc_type>/<id>`
## 后续扩展
后续可以在 resource 写入稳定后,再增加:
- 高价值 summary 写入 `memory`
- EverMemOS 提炼结果回灌
- Obsidian / OpenViking 双写策略

View File

@ -0,0 +1,29 @@
# commit_memory_skill
## 用途
把已经过标准化和筛选的 case / knowledge 内容写入 OpenViking。
## 当前默认策略
第一阶段只做 resource 写入,不强行做复杂 memory 演化。
- `case` -> `viking://soc/case/<scenario>/<id>`
- `knowledge` -> `viking://soc/knowledge/<doc_type>/<id>`
## 输入
- 标准化后的 case / knowledge JSON 文件
- OpenViking 配置URL / API Key
## 输出
- 写入结果
- 目标 URI
- 成功 / 失败状态
## 成功标准
- 可以把本地标准化样本成功写入 OpenViking
- URI 组织符合 namespace 设计
- 后续可以被检索和引用

View File

@ -0,0 +1,89 @@
"""Commit normalized SOC memory items to OpenViking as structured resources."""
from __future__ import annotations
import argparse
import asyncio
import json
from pathlib import Path
from typing import Any
from memory_gateway.openviking_client import OpenVikingClient
def build_resource_uri(item: dict[str, Any]) -> str:
memory_type = item.get("memory_type")
item_id = item["id"]
if memory_type == "case":
scenario = item.get("scenario", "general")
return f"viking://resources/soc-memory-poc/case/{scenario}/{item_id}.json"
if memory_type == "knowledge":
doc_type = item.get("doc_type", "general")
return f"viking://resources/soc-memory-poc/knowledge/{doc_type}/{item_id}.json"
raise ValueError(f"Unsupported memory_type for commit: {memory_type}")
def load_item(path: str | Path) -> dict[str, Any]:
path = Path(path)
with path.open("r", encoding="utf-8") as f:
return json.load(f)
async def commit_file(path: str | Path, client: OpenVikingClient) -> dict[str, Any]:
item = load_item(path)
uri = build_resource_uri(item)
result = await client.add_resource(
uri=uri,
content=json.dumps(item, ensure_ascii=False, indent=2),
resource_type="json",
wait=False,
)
return {
"path": str(path),
"uri": uri,
"result": result,
}
async def commit_directory(directory: str | Path, client: OpenVikingClient, limit: int | None = None) -> list[dict[str, Any]]:
directory = Path(directory)
paths = sorted(directory.rglob("*.json"))
if limit is not None:
paths = paths[:limit]
results: list[dict[str, Any]] = []
for path in paths:
results.append(await commit_file(path, client))
return results
async def main_async(args: argparse.Namespace) -> None:
client = OpenVikingClient()
try:
if args.path:
result = await commit_file(args.path, client)
print(json.dumps(result, ensure_ascii=False, indent=2))
else:
results = await commit_directory(args.directory, client, limit=args.limit)
print(json.dumps(results, ensure_ascii=False, indent=2))
finally:
await client.close()
def main() -> None:
parser = argparse.ArgumentParser(description="Commit normalized SOC items to OpenViking.")
parser.add_argument("--path", help="Single normalized JSON file to commit")
parser.add_argument("--directory", help="Directory of normalized JSON files to commit")
parser.add_argument("--limit", type=int, default=None, help="Optional limit for directory commits")
args = parser.parse_args()
if not args.path and not args.directory:
parser.error("Either --path or --directory is required")
asyncio.run(main_async(args))
if __name__ == "__main__":
main()