mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-09-30 01:52:29 +00:00
* fix(bm25_index): 修正BM25索引计算中的文档长度归一化问题 修复了在计算BM25相似度时对文档长度进行不正确归一化的bug,确保所有查询都能得到准确的相关性评分。 * up * up * up * up * up * up * up * up * up * up * up * up * up * up * up * up * up * refactor(steps): Rename and adjust indexing step logic - Rename `scan_changes.py` and `reindex.py` to `clear_and_scan.py` - Update implementation details of `ScanChangesStep` and `ClearAndScanStep` - Modify the scheduling mechanism in `WatchChangesStep` - Adjust step registration and parameter configuration in config files - Update related tests to align with the new interface changes * up * feat(daily): replace daily CRUD operations with slug provisioning approach * refactor(tests): migrate CRUD step tests from HTTP server to direct LocalFileStore * up * up * up * up --------- Co-authored-by: huangsen <huangsen.huang@alibaba-inc.com>
77 lines
2.7 KiB
Python
77 lines
2.7 KiB
Python
"""Base class for services that expose jobs over a network protocol."""
|
|
|
|
import json
|
|
import os
|
|
from abc import abstractmethod
|
|
from contextlib import asynccontextmanager
|
|
from typing import TYPE_CHECKING
|
|
|
|
from ..base_component import BaseComponent
|
|
from ..job.base_job import BaseJob
|
|
from ...constants import REME_SERVICE_INFO
|
|
from ...enumeration import ComponentEnum
|
|
|
|
if TYPE_CHECKING:
|
|
from ...application import Application
|
|
|
|
|
|
class BaseService(BaseComponent):
|
|
"""Skeleton for services (HTTP, MCP, ...) that turn jobs into endpoints or tools."""
|
|
|
|
component_type = ComponentEnum.SERVICE
|
|
|
|
def __init__(self, **kwargs):
|
|
super().__init__(**kwargs)
|
|
# Underlying framework instance (FastAPI, FastMCP, ...); populated by build_service().
|
|
self.service = None
|
|
|
|
# ----- Subclass contract ---------------------------------------------
|
|
|
|
@abstractmethod
|
|
def build_service(self, app: "Application") -> None:
|
|
"""Instantiate and configure the underlying server framework."""
|
|
|
|
@abstractmethod
|
|
def add_job(self, job: BaseJob) -> None:
|
|
"""Register a single job as a callable endpoint or tool."""
|
|
|
|
@abstractmethod
|
|
def start_service(self, app: "Application") -> None:
|
|
"""Block on serving requests until shutdown."""
|
|
|
|
# ----- Shared helpers ------------------------------------------------
|
|
|
|
def _lifespan(self, app: "Application", host: str, port: int):
|
|
"""Build an async-context lifespan that brackets the server with app start/close.
|
|
|
|
Publishes the bound address via the REME_SERVICE_INFO environment variable so
|
|
in-process clients can discover where this service is listening.
|
|
"""
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(_):
|
|
await app.start()
|
|
service_info = json.dumps({"host": host, "port": port})
|
|
os.environ[REME_SERVICE_INFO] = service_info
|
|
self.logger.info(f"{self.name} started: {REME_SERVICE_INFO}={service_info}")
|
|
yield
|
|
await app.close()
|
|
|
|
return lifespan
|
|
|
|
def add_jobs(self, app: "Application") -> None:
|
|
"""Register every job whose enable_serve flag is True."""
|
|
for name, job in app.context.jobs.items():
|
|
if not job.enable_serve:
|
|
continue
|
|
try:
|
|
self.add_job(job)
|
|
self.logger.info(f"Added job: {name}")
|
|
except Exception as e:
|
|
self.logger.error(f"Failed to add job {name}: {e}")
|
|
|
|
def run_app(self, app: "Application") -> None:
|
|
"""Build the service, register jobs, then start serving (blocking)."""
|
|
self.build_service(app)
|
|
self.add_jobs(app)
|
|
self.start_service(app)
|