mirror of
https://github.com/volcengine/OpenViking.git
synced 2026-09-28 19:53:23 +08:00
* feat(sdk): sync go/ts/python SDKs with server find/search, recall, and admin changes Server-side changes recently landed that the language SDKs had drifted from: - find/search results now return `tags` and no longer return `category`/`match_reason`/`relations`/`overview` (#3730). Go's strict struct was the only one broken; update MatchedContext accordingly. - new admin endpoints for agent-evolution and per-account settings (#3695). - public `search/recall` endpoint was missing from all SDKs. Changes: - python: add `level`/`since`/`until`/`time_field` to find/search; add an `extra` escape hatch to find/search/add_resource/write/batch_write so new server fields can be passed without an SDK bump (only forwarded when set, preserving `level=0`); add `recall` and the four admin methods. - go: fix MatchedContext (add Tags, drop removed fields), add Recall and the four admin methods. - typescript: type MatchedContext/FindResult, add RecallOptions, add `recall` and the four admin methods. Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> feat(sdk): unify options APIs and sync latest server interfaces - migrate complex Python SDK calls to typed options dictionaries - add dedicated context search and consistent extra-field handling - align Go and TypeScript options with omission-aware serialization - support session config, event tags, Agent Evolution date filters, OpenViking Assets, batch write, downloads, and create_parent - refresh SDK tests and examples across all three languages Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): address options API review findings - fix Go session extra merging and Python message precedence - adapt LangChain calls to the Python options API - migrate repository examples, tests, and documentation Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): complete options migration and message parity - migrate remaining Python SDK benchmarks to options dictionaries - normalize empty parts consistently for single and batch messages - add regression guards for repository SDK call sites Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): align reindex options after main rebase - preserve reindex tags in Python typed options - add reindex extra support for Go and TypeScript - reject official fields passed through extra across SDKs Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> feat(sdk): support legacy keyword options Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> docs(sdk): use explicit Python SDK arguments Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): support set tags extra options Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): expose Go add resource options Expose AddType and ProcessingMode through Go AddResourceOptions and serialize them to the resources API. Add a regression test covering the resulting request payload. Co-authored-by: TRAE CLI <noreply@bytedance.com> Co-authored-by: TRAE CLI <traecli@bytedance.com> feat(sdk): flatten core Python client options Co-authored-by: TRAE CLI <traecli@bytedance.com> docs(sdk): align Python examples with flattened options Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): preserve core API compatibility Co-authored-by: TRAE CLI <traecli@bytedance.com> refactor(python-sdk): move resource hints to options Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): align resource option callers Co-authored-by: TRAE CLI <traecli@bytedance.com> test(sdk): cover recursive reindex forwarding Co-authored-by: TRAE CLI <traecli@bytedance.com> fix(sdk): preserve Go options compatibility Co-authored-by: TRAE CLI <traecli@bytedance.com> feat(python-sdk): expose message peer id Co-authored-by: TRAE CLI <traecli@bytedance.com> test(python-sdk): consolidate options coverage Co-authored-by: TRAE CLI <traecli@bytedance.com> feat(python-sdk): add parts and flatten image search Co-authored-by: TRAE CLI <traecli@bytedance.com> * docs(sdk): align Python call examples Co-authored-by: TRAE CLI <traecli@bytedance.com> --------- Co-authored-by: TRAE CLI <traecli@bytedance.com> Co-authored-by: Qin Haojie <qinhaojie.exe@bytedance.com>
223 lines
8.6 KiB
Python
223 lines
8.6 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Bob — 新入职成员的使用流程
|
||
|
||
操作:浏览团队资源 → 回顾团队记忆 → 添加自己的资源 → 对话 → 沉淀记忆 → 带上下文搜索
|
||
|
||
获取 API Key:
|
||
API Key 由租户管理员分配,流程如下:
|
||
|
||
1. 管理员(如 Alice)用自己的 Key 注册 Bob:
|
||
curl -X POST http://localhost:1933/api/v1/admin/accounts/demo-team/users \
|
||
-H "X-API-Key: <alice_key>" -H "Content-Type: application/json" \
|
||
-d '{"user_id": "bob", "role": "user"}'
|
||
返回中的 user_key 就是 Bob 的 API Key
|
||
2. 或者运行 setup_users.py 自动完成,Key 写入 user_keys.json
|
||
|
||
运行(建议在 alice.py 之后执行,这样可以看到 Alice 沉淀的团队记忆):
|
||
uv run examples/cloud/bob.py
|
||
uv run examples/cloud/bob.py --url http://localhost:1933 --api-key <bob_key>
|
||
"""
|
||
|
||
import argparse
|
||
import json
|
||
import sys
|
||
import time
|
||
|
||
import openviking as ov
|
||
from openviking_cli.utils.async_utils import run_async
|
||
|
||
|
||
def load_key_from_file(user="bob"):
|
||
try:
|
||
with open("examples/cloud/user_keys.json") as f:
|
||
keys = json.load(f)
|
||
return keys["url"], keys[f"{user}_key"]
|
||
except (FileNotFoundError, KeyError):
|
||
return None, None
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description="Bob 的使用流程")
|
||
parser.add_argument("--url", default=None, help="Server URL")
|
||
parser.add_argument("--api-key", default=None, help="Bob 的 API Key")
|
||
args = parser.parse_args()
|
||
|
||
url, api_key = args.url, args.api_key
|
||
if not api_key:
|
||
url_from_file, key_from_file = load_key_from_file("bob")
|
||
url = url or url_from_file or "http://localhost:1933"
|
||
api_key = key_from_file
|
||
if not url:
|
||
url = "http://localhost:1933"
|
||
if not api_key:
|
||
print("请通过 --api-key 指定 API Key,或先运行 setup_users.py")
|
||
sys.exit(1)
|
||
|
||
print(f"Server: {url}")
|
||
print("User: bob")
|
||
print("Key: [hidden]")
|
||
|
||
client = ov.SyncHTTPClient(url=url, api_key=api_key)
|
||
client.initialize()
|
||
|
||
try:
|
||
# ── 1. 浏览团队已有资源 ──
|
||
print("\n== 1. 浏览团队资源 ==")
|
||
entries = client.ls("viking://")
|
||
if not entries:
|
||
print(" (空,Alice 还没添加资源)")
|
||
for entry in entries:
|
||
if isinstance(entry, dict):
|
||
kind = "dir " if entry.get("isDir") else "file"
|
||
print(f" [{kind}] {entry.get('name', '?')}")
|
||
|
||
# ── 2. 回顾团队记忆(Alice 沉淀的技术决策) ──
|
||
print("\n== 2. 回顾团队记忆: '项目技术选型' ==")
|
||
results = client.find(query="项目用了什么技术栈和架构选型", limit=5)
|
||
memories = results.get("memories", [])
|
||
if memories:
|
||
print(" 团队记忆:")
|
||
for index, memory in enumerate(memories, 1):
|
||
description = (
|
||
memory.get("abstract")
|
||
or memory.get("overview")
|
||
or memory.get("uri", "")
|
||
)
|
||
print(f" {index}. [{memory.get('score', 0.0):.3f}] {description[:150]}")
|
||
else:
|
||
print(" 未找到团队记忆(Alice 可能还没执行 commit)")
|
||
resources = results.get("resources", [])
|
||
if resources:
|
||
print(" 相关资源:")
|
||
for index, resource in enumerate(resources, 1):
|
||
print(
|
||
f" {index}. [{resource.get('score', 0.0):.3f}] "
|
||
f"{resource['uri']}"
|
||
)
|
||
|
||
# ── 3. 搜索具体决策 ──
|
||
print("\n== 3. 搜索: '存储方案 TOS 配置' ==")
|
||
results = client.find(query="文件存储方案 TOS bucket 配置", limit=3)
|
||
memories = results.get("memories", [])
|
||
if memories:
|
||
for index, memory in enumerate(memories, 1):
|
||
description = (
|
||
memory.get("abstract")
|
||
or memory.get("overview")
|
||
or memory.get("uri", "")
|
||
)
|
||
print(f" {index}. [{memory.get('score', 0.0):.3f}] {description[:150]}")
|
||
else:
|
||
print(" 未找到相关记忆")
|
||
|
||
# ── 4. 添加自己的资源 ──
|
||
print("\n== 4. 添加资源: CONTRIBUTING.md ==")
|
||
result = client.add_resource(
|
||
path="https://raw.githubusercontent.com/volcengine/OpenViking/refs/heads/main/CONTRIBUTING.md",
|
||
options={"reason": "贡献指南学习笔记"},
|
||
)
|
||
bob_uri = result.get("root_uri", "")
|
||
print(f" URI: {bob_uri}")
|
||
print(" 等待处理...")
|
||
client.wait_processed(timeout=120)
|
||
print(" 完成")
|
||
|
||
# ── 5. 创建会话,模拟入职学习 ──
|
||
print("\n== 5. 对话: 入职学习 ==")
|
||
session_info = client.create_session()
|
||
session = client.session(session_id=session_info["session_id"])
|
||
print(f" Session: {session.session_id}")
|
||
|
||
messages = [
|
||
("user", "我刚入职,需要了解 OpenViking 的贡献流程"),
|
||
(
|
||
"assistant",
|
||
"欢迎!贡献流程主要是:1) Fork 仓库 2) 创建 feature branch "
|
||
"3) 提交 PR 并通过 CI 4) Code Review 后合并。"
|
||
"代码规范见 CONTRIBUTING.md。",
|
||
),
|
||
("user", "本地开发环境怎么搭建?"),
|
||
(
|
||
"assistant",
|
||
"本地开发步骤:1) 安装 Python 3.10+ 和 uv "
|
||
"2) git clone 后执行 uv sync 安装依赖 "
|
||
"3) 复制 examples/ov.conf.example 为 ~/.openviking/ov.conf 填入 API Key "
|
||
"4) 运行 openviking-server 启动开发服务。构建 abi3 C++ 扩展需要 cmake。",
|
||
),
|
||
("user", "测试怎么跑?"),
|
||
(
|
||
"assistant",
|
||
"运行测试:1) uv run pytest 跑全量测试 "
|
||
"2) uv run pytest tests/unit -x 只跑单元测试 "
|
||
"3) CI 会自动跑 lint + test,PR 合并前必须全绿。",
|
||
),
|
||
]
|
||
for role, content in messages:
|
||
run_async(session.add_message(role=role, content=content))
|
||
print(f" 添加了 {len(messages)} 条消息")
|
||
|
||
# ── 6. 沉淀记忆 ──
|
||
print("\n== 6. 沉淀记忆: commit session ==")
|
||
print(" 正在提取(开发流程、环境配置等)...")
|
||
client.commit_session(session.session_id)
|
||
print(" commit 完成")
|
||
time.sleep(2)
|
||
client.wait_processed(timeout=120)
|
||
print(" 记忆向量化完成")
|
||
|
||
# ── 7. 回顾自己的记忆 ──
|
||
print("\n== 7. 回顾记忆: '本地开发环境搭建' ==")
|
||
results = client.find(query="本地开发环境搭建步骤", limit=3)
|
||
memories = results.get("memories", [])
|
||
if memories:
|
||
print(" 记忆:")
|
||
for index, memory in enumerate(memories, 1):
|
||
description = (
|
||
memory.get("abstract")
|
||
or memory.get("overview")
|
||
or memory.get("uri", "")
|
||
)
|
||
print(f" {index}. [{memory.get('score', 0.0):.3f}] {description[:150]}")
|
||
resources = results.get("resources", [])
|
||
if resources:
|
||
print(" 资源:")
|
||
for index, resource in enumerate(resources, 1):
|
||
print(
|
||
f" {index}. [{resource.get('score', 0.0):.3f}] "
|
||
f"{resource['uri']}"
|
||
)
|
||
|
||
# ── 8. 带会话上下文的搜索 ──
|
||
print("\n== 8. 带上下文搜索: '还有什么注意事项' ==")
|
||
results = client.search(
|
||
query="还有什么需要注意的事项",
|
||
session_id=session.session_id,
|
||
limit=3,
|
||
)
|
||
resources = results.get("resources", [])
|
||
if resources:
|
||
for index, resource in enumerate(resources, 1):
|
||
print(
|
||
f" {index}. [{resource.get('score', 0.0):.3f}] "
|
||
f"{resource['uri']}"
|
||
)
|
||
memories = results.get("memories", [])
|
||
if memories:
|
||
for index, memory in enumerate(memories, 1):
|
||
description = (
|
||
memory.get("abstract")
|
||
or memory.get("overview")
|
||
or memory.get("uri", "")
|
||
)
|
||
print(f" {index}. [{memory.get('score', 0.0):.3f}] {description[:100]}")
|
||
|
||
print("\nBob 流程完成")
|
||
|
||
finally:
|
||
client.close()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|