Initial SOC memory POC implementation
This commit is contained in:
36
skills/commit_memory_skill/README.md
Normal file
36
skills/commit_memory_skill/README.md
Normal 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 双写策略
|
||||
29
skills/commit_memory_skill/SKILL.md
Normal file
29
skills/commit_memory_skill/SKILL.md
Normal 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 设计
|
||||
- 后续可以被检索和引用
|
||||
89
skills/commit_memory_skill/commit_to_openviking.py
Normal file
89
skills/commit_memory_skill/commit_to_openviking.py
Normal 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()
|
||||
Reference in New Issue
Block a user