mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-09-30 01:52:29 +00:00
Reframe digest as the abstract memory layer (details stay in the daily/
resource material; digest holds principles, patterns, precedents reachable
via derived_from provenance edges). Replaces the old digester with a
2-phase ReAct workflow + a daily-tick wrapper:
- Phase 1 (Dreamer extract): clusters material into orthogonal memory
sub-units; each sub-unit maps 1:1 to a digest node (no inner atom
enumeration). Biases toward fewer / richer sub-units.
- Phase 2 (Dreamer integrate per sub-unit): cross-bucket recall +
exactly one write decision (CREATE / UPDATE / SKIP); UPDATE shapes
surfaced explicitly (corroborate / refine / correct).
- CronDreamer: scans <daily_dir>/<today>.md + <daily_dir>/<today>/**
+ <resource_dir>/<today>/** and runs dream_one per file.
Write tools are proper subclasses of the canonical file_io WriteStep /
EditStep with only path-shape + bucket + E-1 edge-conservation rules
layered on top:
- DigestWriteStep(WriteStep): path = <digest_dir>/<bucket>/<slug>.md,
must-not-exist, schema mirrors `write` (path / name / description /
content) so frontmatter lands automatically.
- DigestEditStep(EditStep): body-only find-and-replace + must-exist +
E-1 conservation preflight (refuses if any outbound wikilink would
be dropped).
Configuration:
- Bucket vocabulary structured in code (tuple[{name, description}]);
prompt renders the heuristic block at runtime via {buckets}.
- digest_dir / daily_dir / resource_dir come from app config (not tool
params); prompts use {digest_dir} placeholder.
- BaseStep walks class MRO when loading prompts, so subclasses inherit
parent yaml without duplication.
Tooling: agentscope register_tool_function schemas now wrap in the
proper {"type":"function","function":{...}} envelope. OpenAIAsLLM
routes base_url through client_kwargs so non-default endpoints work.
Smoke: tests4/smoke/{_dreamer_fixture.py,test_dreamer_inproc.py,
test_dreamer_cli.sh} drive the end-to-end pipeline.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
59 lines
1.6 KiB
Python
59 lines
1.6 KiB
Python
"""AgentScope LLM model wrappers."""
|
|
|
|
from agentscope.model import AnthropicChatModel, ChatModelBase, OpenAIChatModel
|
|
|
|
from ..base_component import BaseComponent
|
|
from ..component_registry import R
|
|
from ...enumeration import ComponentEnum
|
|
|
|
|
|
class BaseAsLLM(BaseComponent):
|
|
"""Base wrapper for AgentScope chat models. Builds ``self.model`` in ``_start``."""
|
|
|
|
component_type = ComponentEnum.AS_LLM
|
|
|
|
def __init__(self, **kwargs) -> None:
|
|
super().__init__(**kwargs)
|
|
self.model: ChatModelBase | None = None
|
|
|
|
async def _close(self) -> None:
|
|
self.model = None
|
|
|
|
|
|
@R.register("openai")
|
|
class OpenAIAsLLM(BaseAsLLM):
|
|
"""OpenAI chat model wrapper."""
|
|
|
|
async def _start(self) -> None:
|
|
kwargs = dict(self.kwargs)
|
|
base_url = kwargs.pop("base_url", None)
|
|
if base_url:
|
|
client_kwargs = dict(kwargs.pop("client_kwargs", None) or {})
|
|
client_kwargs.setdefault("base_url", base_url)
|
|
kwargs["client_kwargs"] = client_kwargs
|
|
self.model = OpenAIChatModel(**kwargs)
|
|
|
|
async def _close(self) -> None:
|
|
if self.model is not None:
|
|
assert isinstance(self.model, OpenAIChatModel)
|
|
await self.model.client.close()
|
|
|
|
|
|
@R.register("anthropic")
|
|
class AnthropicAsLLM(BaseAsLLM):
|
|
"""Anthropic chat model wrapper."""
|
|
|
|
async def _start(self) -> None:
|
|
self.model = AnthropicChatModel(**self.kwargs)
|
|
|
|
async def _close(self) -> None:
|
|
if self.model is not None:
|
|
assert isinstance(self.model, AnthropicChatModel)
|
|
await self.model.client.close()
|
|
|
|
|
|
__all__ = [
|
|
"BaseAsLLM",
|
|
"OpenAIAsLLM",
|
|
"AnthropicAsLLM",
|
|
]
|