Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: 02. Main Branch Checks

on:
workflow_dispatch:
push:
branches: [ main ]
paths-ignore:
Expand All @@ -16,6 +17,11 @@ on:
- '.gitignore'
- '.editorconfig'

permissions:
actions: read
contents: read
security-events: write

jobs:
test-full:
uses: ./.github/workflows/_test_full.yml
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: 01. Pull Request Checks

on:
workflow_dispatch:
pull_request:
branches: [ main, develop ]
paths-ignore:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/schedule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ on:
schedule:
- cron: '0 0 * * 0' # Run at 00:00 on Sunday

permissions:
actions: read
contents: read
security-events: write

jobs:
security-scan:
uses: ./.github/workflows/_codeql.yml
3 changes: 3 additions & 0 deletions docs/en/configuration/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ client = ov.AsyncOpenViking(config=config)
}
```

Notes:
- `storage.vectordb.sparse_weight` controls hybrid (dense + sparse) indexing/search. It only takes effect when you use a hybrid index; set it > 0 to enable sparse signals.

## Related Documentation

- [Embedding Configuration](./embedding.md) - Embedding setup
Expand Down
3 changes: 3 additions & 0 deletions docs/zh/configuration/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ client = ov.AsyncOpenViking(config=config)
}
```

说明:
- `storage.vectordb.sparse_weight` 用于混合(dense + sparse)索引/检索的权重,仅在使用 hybrid 索引时生效;设置为 > 0 才会启用 sparse 信号。

## 相关文档

- [Embedding 配置](./embedding.md) - Embedding 设置
Expand Down
27 changes: 16 additions & 11 deletions openviking/agfs_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,19 @@ class AGFSManager:
manager.start()

# 2. S3 backend
from openviking.utils.config.agfs_config import AGFSConfig, S3Config

config = AGFSConfig(
path="./data",
port=8080,
backend="s3",
s3_bucket="my-bucket",
s3_region="us-east-1",
s3_access_key="your-access-key",
s3_secret_key="your-secret-key",
s3=S3Config(
bucket="my-bucket",
region="us-east-1",
access_key="your-access-key",
secret_key="your-secret-key",
endpoint="https://s3.amazonaws.com"
),
log_level="debug"
)
manager = AGFSManager(config=config)
Expand Down Expand Up @@ -73,13 +78,13 @@ def __init__(
self.port = config.port
self.log_level = config.log_level
self.backend = config.backend
self.s3_bucket = config.s3_bucket
self.s3_region = config.s3_region
self.s3_access_key = config.s3_access_key
self.s3_secret_key = config.s3_secret_key
self.s3_endpoint = config.s3_endpoint
self.s3_prefix = config.s3_prefix
self.s3_use_ssl = config.s3_use_ssl
self.s3_bucket = config.s3.bucket
self.s3_region = config.s3.region
self.s3_access_key = config.s3.access_key
self.s3_secret_key = config.s3.secret_key
self.s3_endpoint = config.s3.endpoint
self.s3_prefix = config.s3.prefix
self.s3_use_ssl = config.s3.use_ssl

self.process: Optional[subprocess.Popen] = None
self.config_file: Optional[Path] = None
Expand Down
51 changes: 18 additions & 33 deletions openviking/session/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
Session as Context: Sessions integrated into L0/L1/L2 system.
"""

import asyncio
import json
import re
from dataclasses import dataclass, field
Expand All @@ -14,7 +13,7 @@
from uuid import uuid4

from openviking.message import Message, Part
from openviking.utils import get_logger
from openviking.utils import get_logger, run_async
from openviking.utils.config import get_openviking_config

if TYPE_CHECKING:
Expand All @@ -25,20 +24,6 @@
logger = get_logger(__name__)


def _run_async(coro):
"""Run async coroutine."""
try:
loop = asyncio.get_running_loop()
# If already in event loop, use nest_asyncio or return directly
import nest_asyncio

nest_asyncio.apply()
return loop.run_until_complete(coro)
except RuntimeError:
# No running event loop, use asyncio.run()
return asyncio.run(coro)


@dataclass
class SessionCompression:
"""Session compression information."""
Expand Down Expand Up @@ -109,7 +94,7 @@ def load(self):
return

try:
content = _run_async(
content = run_async(
self._viking_fs.read_file(f"{self._session_uri}/messages.jsonl")
)
self._messages = [
Expand All @@ -123,7 +108,7 @@ def load(self):

# Restore compression_index (scan history directory)
try:
history_items = _run_async(self._viking_fs.ls(f"{self._session_uri}/history"))
history_items = run_async(self._viking_fs.ls(f"{self._session_uri}/history"))
archives = [
item["name"] for item in history_items if item["name"].startswith("archive_")
]
Expand Down Expand Up @@ -254,7 +239,7 @@ def commit(self) -> Dict[str, Any]:
logger.info(
f"Starting memory extraction from {len(messages_to_archive)} archived messages"
)
memories = _run_async(
memories = run_async(
self._session_compressor.extract_long_term_memories(
messages=messages_to_archive,
user=self.user,
Expand Down Expand Up @@ -298,7 +283,7 @@ def _update_active_counts(self) -> int:

for usage in self._usage_records:
try:
_run_async(
run_async(
storage.update(
collection="context",
filter={"uri": usage.uri},
Expand Down Expand Up @@ -334,7 +319,7 @@ def get_context_for_search(
summaries = []
if self.compression.compression_index > 0:
try:
history_items = _run_async(self._viking_fs.ls(f"{self._session_uri}/history"))
history_items = run_async(self._viking_fs.ls(f"{self._session_uri}/history"))
query_lower = query.lower()

# Collect all archives with relevance scores
Expand All @@ -344,7 +329,7 @@ def get_context_for_search(
if name and name.startswith("archive_"):
overview_uri = f"{self._session_uri}/history/{name}/.overview.md"
try:
overview = _run_async(self._viking_fs.read_file(overview_uri))
overview = run_async(self._viking_fs.read_file(overview_uri))
# Calculate relevance by keyword matching
score = 0
if query_lower in overview.lower():
Expand Down Expand Up @@ -397,7 +382,7 @@ def _generate_archive_summary(self, messages: List[Message]) -> str:
"compression.structured_summary",
{"messages": formatted},
)
return _run_async(vlm.get_completion_async(prompt))
return run_async(vlm.get_completion_async(prompt))
except Exception as e:
logger.warning(f"LLM summary failed: {e}")

Expand All @@ -420,15 +405,15 @@ def _write_archive(

# Write messages.jsonl
lines = [m.to_jsonl() for m in messages]
_run_async(
run_async(
viking_fs.write_file(
uri=f"{archive_uri}/messages.jsonl",
content="\n".join(lines) + "\n",
)
)

_run_async(viking_fs.write_file(uri=f"{archive_uri}/.abstract.md", content=abstract))
_run_async(viking_fs.write_file(uri=f"{archive_uri}/.overview.md", content=overview))
run_async(viking_fs.write_file(uri=f"{archive_uri}/.abstract.md", content=abstract))
run_async(viking_fs.write_file(uri=f"{archive_uri}/.overview.md", content=overview))

logger.debug(f"Written archive: {archive_uri}")

Expand All @@ -446,21 +431,21 @@ def _write_to_agfs(self, messages: List[Message]) -> None:
lines = [m.to_jsonl() for m in messages]
content = "\n".join(lines) + "\n" if lines else ""

_run_async(
run_async(
viking_fs.write_file(
uri=f"{self._session_uri}/messages.jsonl",
content=content,
)
)

# Update L0/L1
_run_async(
run_async(
viking_fs.write_file(
uri=f"{self._session_uri}/.abstract.md",
content=abstract,
)
)
_run_async(
run_async(
viking_fs.write_file(
uri=f"{self._session_uri}/.overview.md",
content=overview,
Expand All @@ -471,7 +456,7 @@ def _append_to_jsonl(self, msg: Message) -> None:
"""Append to messages.jsonl."""
if not self._viking_fs:
return
_run_async(
run_async(
self._viking_fs.append_file(
f"{self._session_uri}/messages.jsonl",
msg.to_jsonl() + "\n",
Expand All @@ -485,7 +470,7 @@ def _update_message_in_jsonl(self) -> None:

lines = [m.to_jsonl() for m in self._messages]
content = "\n".join(lines) + "\n"
_run_async(
run_async(
self._viking_fs.write_file(
f"{self._session_uri}/messages.jsonl",
content,
Expand Down Expand Up @@ -516,7 +501,7 @@ def _save_tool_result(
"status": status,
"time": {"created": datetime.now().isoformat()},
}
_run_async(
run_async(
self._viking_fs.write_file(
f"{self._session_uri}/tools/{tool_id}/tool.json",
json.dumps(tool_data, ensure_ascii=False),
Expand Down Expand Up @@ -563,7 +548,7 @@ def _write_relations(self) -> None:
viking_fs = self._viking_fs
for usage in self._usage_records:
try:
_run_async(viking_fs.link(self._session_uri, usage.uri))
run_async(viking_fs.link(self._session_uri, usage.uri))
logger.debug(f"Created relation: {self._session_uri} -> {usage.uri}")
except Exception as e:
logger.warning(f"Failed to create relation to {usage.uri}: {e}")
Expand Down
4 changes: 2 additions & 2 deletions openviking/storage/observers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Monitors queue system status (Embedding, Semantic, and custom queues).
import openviking as ov

client = ov.OpenViking(path="./data")
print(client.observers["queue"])
print(client.observer.queue)
# Output:
# Queue Pending In Progress Processed Errors Total
# Embedding 5 2 100 0 107
Expand All @@ -58,7 +58,7 @@ Monitors VikingDB collection status (index count and vector count per collection
import openviking as ov

client = ov.OpenViking(path="./data")
print(client.observers["vikingdb"])
print(client.observer.vikingdb)
# Output:
# Collection Index Count Vector Count Status
# context 1 69 OK
Expand Down
40 changes: 0 additions & 40 deletions openviking/storage/observers/async_utils.py

This file was deleted.

4 changes: 2 additions & 2 deletions openviking/storage/observers/queue_observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

from typing import Dict

from openviking.storage.observers.async_utils import run_coroutine_sync
from openviking.storage.observers.base_observer import BaseObserver
from openviking.storage.queuefs.named_queue import QueueStatus
from openviking.storage.queuefs.queue_manager import QueueManager
from openviking.utils import run_async
from openviking.utils.logger import get_logger

logger = get_logger(__name__)
Expand All @@ -32,7 +32,7 @@ async def get_status_table_async(self) -> str:
return self._format_status_as_table(statuses)

def get_status_table(self) -> str:
return run_coroutine_sync(self.get_status_table_async)
return run_async(self.get_status_table_async())

def __str__(self) -> str:
return self.get_status_table()
Expand Down
6 changes: 3 additions & 3 deletions openviking/storage/observers/vikingdb_observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

from typing import Dict

from openviking.storage.observers.async_utils import run_coroutine_sync
from openviking.storage.observers.base_observer import BaseObserver
from openviking.storage.vikingdb_manager import VikingDBManager
from openviking.utils import run_async
from openviking.utils.logger import get_logger

logger = get_logger(__name__)
Expand Down Expand Up @@ -39,7 +39,7 @@ async def get_status_table_async(self) -> str:
return self._format_status_as_table(statuses)

def get_status_table(self) -> str:
return run_coroutine_sync(self.get_status_table_async)
return run_async(self.get_status_table_async())

def __str__(self) -> str:
return self.get_status_table()
Expand Down Expand Up @@ -156,7 +156,7 @@ def has_errors(self) -> bool:
try:
if not self._vikingdb_manager:
return True
run_coroutine_sync(self._vikingdb_manager.health_check)
run_async(self._vikingdb_manager.health_check())
return False
except Exception as e:
logger.error(f"VikingDB health check failed: {e}")
Expand Down
Loading
Loading