Files
OpenViking/examples/basic-usage/basic_usage.py
T
9eac8a6d3d feat(sdk): sync go/ts/python SDKs with server find/search, recall, an… (#3737)
* 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>
2026-08-24 14:09:11 +08:00

316 lines
9.6 KiB
Python

#!/usr/bin/env python3
"""
OpenViking Basic Usage Example
This script demonstrates the core features of OpenViking:
1. HTTP client initialization
2. Adding resources (URLs, files, directories)
3. Browsing the virtual filesystem
4. Semantic search and retrieval
5. Tiered context loading (L0/L1/L2)
6. Session management for memory
Requirements:
- pip install openviking --upgrade
- A running OpenViking server at http://localhost:1933
"""
import os
import sys
# Add parent directory to path for local development
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
def main():
print("=" * 60)
print("OpenViking Basic Usage Example")
print("=" * 60)
print()
# ============================================================
# 1. Initialization
# ============================================================
print("1. Initializing OpenViking...")
print("-" * 40)
try:
from openviking_sdk import SyncHTTPClient
except ImportError as e:
print(f" Error: Failed to import openviking_sdk: {e}")
print(" Please install: pip install openviking-sdk --upgrade")
sys.exit(1)
client = SyncHTTPClient(url="http://localhost:1933")
try:
client.initialize()
print(" Client initialized successfully")
# Check health status
if client.is_healthy():
print(" Status: healthy")
else:
print(" Warning: Some components may not be healthy")
except Exception as e:
print(f" Error during initialization: {e}")
print(" Make sure the OpenViking server is running")
sys.exit(1)
print()
# ============================================================
# 2. Adding Resources
# ============================================================
print("2. Adding a resource (URL)...")
print("-" * 40)
try:
# Add a URL resource
result = client.add_resource(
path="https://raw.githubusercontent.com/volcengine/OpenViking/refs/heads/main/README.md",
wait=False, # Non-blocking, process in background
)
root_uri = result.get("root_uri", "")
print(f" Root URI: {root_uri}")
# Get the file count
files = client.ls(uri=root_uri)
print(f" Files indexed: {len(files)}")
except Exception as e:
print(f" Error adding resource: {e}")
root_uri = ""
print()
# ============================================================
# 3. Browsing the Virtual Filesystem
# ============================================================
print("3. Browsing the virtual filesystem...")
print("-" * 40)
if root_uri:
try:
# List directory contents
print(" Directory listing:")
files = client.ls(uri=root_uri, simple=True)
for f in files[:5]: # Show first 5 files
print(f" - {f}")
# Show tree structure
print("\n Tree view:")
tree = client.tree(uri=root_uri, level_limit=2)
print_tree(tree, indent=" ")
except Exception as e:
print(f" Error browsing filesystem: {e}")
print()
# ============================================================
# 4. Waiting for Semantic Processing
# ============================================================
print("4. Waiting for semantic processing...")
print("-" * 40)
try:
# Wait for all async operations to complete
status = client.wait_processed(timeout=60)
print(f" Processing complete: {status}")
except Exception as e:
print(f" Note: {e}")
print(" Continuing without waiting...")
print()
# ============================================================
# 5. Tiered Context Loading
# ============================================================
print("5. Tiered Context Loading (L0/L1/L2):")
print("-" * 40)
if root_uri:
try:
# L0: Abstract (quick summary ~100 tokens)
print(" L0 (Abstract):")
abstract = client.abstract(uri=root_uri)
if abstract:
# Show first 200 characters
preview = abstract[:200] + "..." if len(abstract) > 200 else abstract
print(f" {preview}")
else:
print(" (Not available yet)")
print()
# L1: Overview (key points ~2k tokens)
print(" L1 (Overview):")
overview = client.overview(uri=root_uri)
if overview:
preview = overview[:300] + "..." if len(overview) > 300 else overview
print(f" {preview}")
else:
print(" (Not available yet)")
print()
# L2: Read one concrete file under the resource root
print(" L2 (Full content - first 500 chars):")
glob_result = client.glob(pattern="**/*.md", uri=root_uri)
matches = glob_result.get("matches", []) if isinstance(glob_result, dict) else []
if matches:
content = client.read(uri=matches[0])
preview = content[:500] + "..." if len(content) > 500 else content
print(f" File: {matches[0]}")
print(f" {preview}")
else:
print(" (No readable markdown file found under this resource)")
except Exception as e:
print(f" Error loading context: {e}")
print()
# ============================================================
# 6. Semantic Search
# ============================================================
print("6. Semantic Search:")
print("-" * 40)
if root_uri:
try:
query = "what is openviking"
print(f" Query: '{query}'")
print(" Results:")
results = client.find(
query=query,
target_uri=root_uri,
limit=5,
)
resources = results.get("resources", [])
if resources:
for resource in resources:
print(f" - {resource['uri']}")
print(f" Score: {resource.get('score', 0.0):.4f}")
else:
print(" No results found")
except Exception as e:
print(f" Error during search: {e}")
print()
# ============================================================
# 7. Content Search (grep)
# ============================================================
print("7. Content search (grep):")
print("-" * 40)
if root_uri:
try:
pattern = "Agent"
print(f" Pattern: '{pattern}'")
result = client.grep(uri=root_uri, pattern=pattern, case_insensitive=True)
matches = result.get("matches", [])
print(f" Found {len(matches)} matches")
# Show first 3 matches
for match in matches[:3]:
print(f" - {match.get('uri', 'N/A')}: {match.get('count', 0)} occurrences")
except Exception as e:
print(f" Error during grep: {e}")
print()
# ============================================================
# 8. Session Management (Optional Demo)
# ============================================================
print("8. Session Management (Demo):")
print("-" * 40)
try:
# Create a new session
session_info = client.create_session()
session_id = session_info.get("session_id", "")
print(f" Created session: {session_id}")
# Add a conversation turn
client.add_message(
session_id=session_id,
role="user",
content="I prefer Python for data science projects",
)
client.add_message(
session_id=session_id,
role="assistant",
content="Understood! I'll use Python for your data science work.",
)
print(" Added conversation turn")
# Note: In a real application, you would commit the session at the end
# to extract long-term memories. Here we just demonstrate the API.
# client.commit_session(session_id)
print(" (Session would be committed at conversation end)")
except Exception as e:
print(f" Note: Session demo skipped - {e}")
print()
# ============================================================
# 9. Cleanup
# ============================================================
print("9. Closing OpenViking...")
print("-" * 40)
try:
client.close()
print(" Done!")
except Exception as e:
print(f" Note: Close skipped - {e}")
print()
print("=" * 60)
print("Example completed successfully!")
print("=" * 60)
def print_tree(tree, indent: str = ""):
"""Helper function to print tree structure."""
if not tree:
return
if isinstance(tree, list):
for child in tree[:5]:
print_tree(child, indent)
return
if not isinstance(tree, dict):
print(f"{indent}{tree}")
return
name = tree.get("name", "?")
children = tree.get("children", [])
is_dir = tree.get("isDir", tree.get("is_dir", bool(children)))
print(f"{indent}{name}/" if is_dir else f"{indent}{name}")
for child in children[:5]: # Limit to first 5 children
if child.get("isDir", child.get("is_dir")):
print_tree(child, indent + " ")
else:
print(f"{indent} {child.get('name', '?')}")
if __name__ == "__main__":
main()