Refactor OpenViking Memory API and User Management

- Updated API authentication headers to use `X-API-Key` for both admin and user APIs.
- Modified the account creation process to directly create user-specific accounts without requiring an admin workspace.
- Enhanced user creation to return account-specific details, including `admin_user_id`.
- Introduced new endpoints for retrieving task status and user profiles, allowing for more flexible user data management.
- Updated search functionality to include additional parameters such as `level` and `score_threshold`.
- Improved the handling of user keys in the storage layer to associate them with specific accounts.
- Added tests to validate the new user account creation process and search functionalities, ensuring proper integration with the OpenViking service.
- Included new documentation to reflect changes in API usage and expected request/response formats.
This commit is contained in:
2026-05-27 16:09:28 +08:00
parent a89807b174
commit 70cda923b2
13 changed files with 543 additions and 165 deletions

View File

@ -103,9 +103,14 @@ class MemorySystemService:
everos_method = "agentic" if request.use_llm else "hybrid"
async def search_openviking() -> dict[str, Any]:
if request.use_llm:
return await self.openviking.search(credential, request.session_id, request.query, request.limit)
return await self.openviking.find(credential, request.query, request.limit)
return await self.openviking.search(
credential,
request.query,
request.limit,
request.level,
request.score_threshold,
request.target_uri,
)
async def search_everos() -> dict[str, Any]:
return await self.everos.search(
@ -160,10 +165,32 @@ class MemorySystemService:
backends=self._compact_session_context_backends(backends),
)
async def get_profile(self, user_id: str) -> ProfileResponse:
backends = {"everos": await self._capture(lambda: self.everos.get_profile(user_id))}
async def get_profile(
self,
user_id: str,
user_key: str,
query: str = "用户画像",
limit: int = 10,
level: int = 2,
) -> ProfileResponse:
credential = self.openviking.credential_for_user(user_id, user_key)
backends = await self._run_backends(
everos=lambda: self.everos.get_profile(user_id),
openviking=lambda: self.openviking.search_profile_memories(credential, query, limit, level),
)
backends = self._remove_vectors_from_backends(backends)
profile = backends["everos"].result if backends["everos"].status == "success" else None
return ProfileResponse(status=self._aggregate_status(backends), profile=profile, backends=backends)
items = (
self._items_from_backend_result("openviking", backends["openviking"].result)[:limit]
if backends["openviking"].status == "success"
else []
)
return ProfileResponse(
status=self._aggregate_status(backends),
profile=profile,
items=items,
backends=self._compact_profile_backends(backends),
)
async def health(self) -> dict[str, Any]:
backends = await self._run_backends(openviking=self.openviking.health, everos=self.everos.health)
@ -323,6 +350,31 @@ class MemorySystemService:
return {key: value for key, value in compact.items() if value is not None}
return self._compact_backend_result(backend_name, result)
def _compact_profile_backends(self, backends: dict[str, BackendStatus]) -> dict[str, BackendStatus]:
return {
name: backend.model_copy(update={"result": self._compact_profile_backend_result(name, backend.result)})
for name, backend in backends.items()
}
def _compact_profile_backend_result(self, backend_name: str, result: Any) -> Any:
if backend_name == "openviking":
return self._compact_backend_result("openviking", result)
if backend_name == "everos":
data = result.get("data") if isinstance(result, dict) and isinstance(result.get("data"), dict) else result
if not isinstance(data, dict):
return result
compact: dict[str, Any] = {}
for key in ("total_count", "count"):
if key in data:
compact[key] = data[key]
compact["counts"] = {
key: len(data.get(key) or [])
for key in ("episodes", "profiles", "agent_cases", "agent_skills")
if isinstance(data.get(key), list)
}
return compact
return result
def _remove_vectors_from_backends(self, backends: dict[str, BackendStatus]) -> dict[str, BackendStatus]:
return {
name: backend.model_copy(update={"result": self._remove_vectors(backend.result)})