remdb 0.2.6__py3-none-any.whl → 0.3.103__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of remdb might be problematic. Click here for more details.
- rem/__init__.py +129 -2
- rem/agentic/README.md +76 -0
- rem/agentic/__init__.py +15 -0
- rem/agentic/agents/__init__.py +16 -2
- rem/agentic/agents/sse_simulator.py +500 -0
- rem/agentic/context.py +7 -5
- rem/agentic/llm_provider_models.py +301 -0
- rem/agentic/providers/phoenix.py +32 -43
- rem/agentic/providers/pydantic_ai.py +84 -10
- rem/api/README.md +238 -1
- rem/api/deps.py +255 -0
- rem/api/main.py +70 -22
- rem/api/mcp_router/server.py +8 -1
- rem/api/mcp_router/tools.py +80 -0
- rem/api/middleware/tracking.py +172 -0
- rem/api/routers/admin.py +277 -0
- rem/api/routers/auth.py +124 -0
- rem/api/routers/chat/completions.py +123 -14
- rem/api/routers/chat/models.py +7 -3
- rem/api/routers/chat/sse_events.py +526 -0
- rem/api/routers/chat/streaming.py +468 -45
- rem/api/routers/dev.py +81 -0
- rem/api/routers/feedback.py +455 -0
- rem/api/routers/messages.py +473 -0
- rem/api/routers/models.py +78 -0
- rem/api/routers/shared_sessions.py +406 -0
- rem/auth/middleware.py +126 -27
- rem/cli/commands/ask.py +15 -11
- rem/cli/commands/configure.py +169 -94
- rem/cli/commands/db.py +53 -7
- rem/cli/commands/experiments.py +278 -96
- rem/cli/commands/process.py +8 -7
- rem/cli/commands/scaffold.py +47 -0
- rem/cli/commands/schema.py +9 -9
- rem/cli/main.py +10 -0
- rem/config.py +2 -2
- rem/models/core/core_model.py +7 -1
- rem/models/entities/__init__.py +21 -0
- rem/models/entities/domain_resource.py +38 -0
- rem/models/entities/feedback.py +123 -0
- rem/models/entities/message.py +30 -1
- rem/models/entities/session.py +83 -0
- rem/models/entities/shared_session.py +206 -0
- rem/models/entities/user.py +10 -3
- rem/registry.py +367 -0
- rem/schemas/agents/rem.yaml +7 -3
- rem/services/content/providers.py +94 -140
- rem/services/content/service.py +85 -16
- rem/services/dreaming/affinity_service.py +2 -16
- rem/services/dreaming/moment_service.py +2 -15
- rem/services/embeddings/api.py +20 -13
- rem/services/phoenix/EXPERIMENT_DESIGN.md +3 -3
- rem/services/phoenix/client.py +252 -19
- rem/services/postgres/README.md +29 -10
- rem/services/postgres/repository.py +132 -0
- rem/services/postgres/schema_generator.py +86 -5
- rem/services/rate_limit.py +113 -0
- rem/services/rem/README.md +14 -0
- rem/services/session/compression.py +17 -1
- rem/services/user_service.py +98 -0
- rem/settings.py +115 -17
- rem/sql/background_indexes.sql +10 -0
- rem/sql/migrations/001_install.sql +152 -2
- rem/sql/migrations/002_install_models.sql +580 -231
- rem/sql/migrations/003_seed_default_user.sql +48 -0
- rem/utils/constants.py +97 -0
- rem/utils/date_utils.py +228 -0
- rem/utils/embeddings.py +17 -4
- rem/utils/files.py +167 -0
- rem/utils/mime_types.py +158 -0
- rem/utils/model_helpers.py +156 -1
- rem/utils/schema_loader.py +273 -14
- rem/utils/sql_types.py +3 -1
- rem/utils/vision.py +9 -14
- rem/workers/README.md +14 -14
- rem/workers/db_maintainer.py +74 -0
- {remdb-0.2.6.dist-info → remdb-0.3.103.dist-info}/METADATA +486 -132
- {remdb-0.2.6.dist-info → remdb-0.3.103.dist-info}/RECORD +80 -57
- {remdb-0.2.6.dist-info → remdb-0.3.103.dist-info}/WHEEL +1 -1
- rem/sql/002_install_models.sql +0 -1068
- rem/sql/install_models.sql +0 -1038
- {remdb-0.2.6.dist-info → remdb-0.3.103.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Scaffold command - generate project structure for REM-based applications.
|
|
3
|
+
|
|
4
|
+
TODO: Implement this command to generate:
|
|
5
|
+
- my_app/main.py (entry point with create_app)
|
|
6
|
+
- my_app/models.py (example CoreModel subclass)
|
|
7
|
+
- my_app/routers/ (example FastAPI router)
|
|
8
|
+
- schemas/agents/ (example agent schema)
|
|
9
|
+
- schemas/evaluators/ (example evaluator)
|
|
10
|
+
- sql/migrations/ (empty migrations directory)
|
|
11
|
+
- pyproject.toml (with remdb dependency)
|
|
12
|
+
- README.md (basic usage instructions)
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
rem scaffold my-app
|
|
16
|
+
rem scaffold my-app --with-examples # Include example models/routers/tools
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import click
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@click.command()
|
|
23
|
+
@click.argument("name")
|
|
24
|
+
@click.option("--with-examples", is_flag=True, help="Include example code")
|
|
25
|
+
def scaffold(name: str, with_examples: bool) -> None:
|
|
26
|
+
"""
|
|
27
|
+
Generate a new REM-based project structure.
|
|
28
|
+
|
|
29
|
+
NAME is the project directory name to create.
|
|
30
|
+
"""
|
|
31
|
+
click.echo(f"TODO: Scaffold command not yet implemented")
|
|
32
|
+
click.echo(f"Would create project: {name}")
|
|
33
|
+
click.echo(f"With examples: {with_examples}")
|
|
34
|
+
click.echo()
|
|
35
|
+
click.echo("For now, manually create this structure:")
|
|
36
|
+
click.echo(f"""
|
|
37
|
+
{name}/
|
|
38
|
+
├── {name.replace('-', '_')}/
|
|
39
|
+
│ ├── main.py # Entry point (create_app + extensions)
|
|
40
|
+
│ ├── models.py # Custom models (inherit CoreModel)
|
|
41
|
+
│ └── routers/ # Custom FastAPI routers
|
|
42
|
+
├── schemas/
|
|
43
|
+
│ ├── agents/ # Custom agent YAML schemas
|
|
44
|
+
│ └── evaluators/ # Custom evaluator schemas
|
|
45
|
+
├── sql/migrations/ # Custom SQL migrations
|
|
46
|
+
└── pyproject.toml
|
|
47
|
+
""")
|
rem/cli/commands/schema.py
CHANGED
|
@@ -29,14 +29,14 @@ from ...services.postgres.schema_generator import SchemaGenerator
|
|
|
29
29
|
"--output",
|
|
30
30
|
"-o",
|
|
31
31
|
type=click.Path(path_type=Path),
|
|
32
|
-
default="
|
|
33
|
-
help="Output SQL file (default:
|
|
32
|
+
default="002_install_models.sql",
|
|
33
|
+
help="Output SQL file (default: 002_install_models.sql)",
|
|
34
34
|
)
|
|
35
35
|
@click.option(
|
|
36
36
|
"--output-dir",
|
|
37
37
|
type=click.Path(path_type=Path),
|
|
38
38
|
default=None,
|
|
39
|
-
help=f"Base output directory (default: {settings.sql_dir})",
|
|
39
|
+
help=f"Base output directory (default: {settings.sql_dir}/migrations)",
|
|
40
40
|
)
|
|
41
41
|
def generate(models: Path, output: Path, output_dir: Path | None):
|
|
42
42
|
"""
|
|
@@ -48,13 +48,13 @@ def generate(models: Path, output: Path, output_dir: Path | None):
|
|
|
48
48
|
- KV_STORE triggers for cache maintenance
|
|
49
49
|
- Indexes (foreground only)
|
|
50
50
|
|
|
51
|
-
Output is written to src/rem/sql/
|
|
51
|
+
Output is written to src/rem/sql/migrations/002_install_models.sql by default.
|
|
52
52
|
|
|
53
53
|
Example:
|
|
54
54
|
rem db schema generate --models src/rem/models/entities
|
|
55
55
|
|
|
56
56
|
This creates:
|
|
57
|
-
- src/rem/sql/
|
|
57
|
+
- src/rem/sql/migrations/002_install_models.sql - Entity tables and triggers
|
|
58
58
|
- src/rem/sql/background_indexes.sql - HNSW indexes (apply after data load)
|
|
59
59
|
|
|
60
60
|
After generation, apply with:
|
|
@@ -62,8 +62,8 @@ def generate(models: Path, output: Path, output_dir: Path | None):
|
|
|
62
62
|
"""
|
|
63
63
|
click.echo(f"Discovering models in {models}")
|
|
64
64
|
|
|
65
|
-
#
|
|
66
|
-
actual_output_dir = output_dir or Path(settings.sql_dir)
|
|
65
|
+
# Default to migrations directory
|
|
66
|
+
actual_output_dir = output_dir or Path(settings.sql_dir) / "migrations"
|
|
67
67
|
generator = SchemaGenerator(output_dir=actual_output_dir)
|
|
68
68
|
|
|
69
69
|
# Generate schema
|
|
@@ -73,10 +73,10 @@ def generate(models: Path, output: Path, output_dir: Path | None):
|
|
|
73
73
|
click.echo(f"✓ Schema generated: {len(generator.schemas)} tables")
|
|
74
74
|
click.echo(f"✓ Written to: {actual_output_dir / output.name}")
|
|
75
75
|
|
|
76
|
-
# Generate background indexes
|
|
76
|
+
# Generate background indexes in parent sql dir
|
|
77
77
|
background_indexes = generator.generate_background_indexes()
|
|
78
78
|
if background_indexes:
|
|
79
|
-
bg_file =
|
|
79
|
+
bg_file = Path(settings.sql_dir) / "background_indexes.sql"
|
|
80
80
|
bg_file.write_text(background_indexes)
|
|
81
81
|
click.echo(f"✓ Background indexes: {bg_file}")
|
|
82
82
|
|
rem/cli/main.py
CHANGED
|
@@ -14,9 +14,17 @@ from pathlib import Path
|
|
|
14
14
|
import click
|
|
15
15
|
from loguru import logger
|
|
16
16
|
|
|
17
|
+
# Import version from package
|
|
18
|
+
try:
|
|
19
|
+
from importlib.metadata import version
|
|
20
|
+
__version__ = version("remdb")
|
|
21
|
+
except Exception:
|
|
22
|
+
__version__ = "unknown"
|
|
23
|
+
|
|
17
24
|
|
|
18
25
|
@click.group()
|
|
19
26
|
@click.option("--verbose", "-v", is_flag=True, help="Enable verbose logging")
|
|
27
|
+
@click.version_option(version=__version__, prog_name="rem")
|
|
20
28
|
def cli(verbose: bool):
|
|
21
29
|
"""REM - Resources Entities Moments system CLI."""
|
|
22
30
|
if verbose:
|
|
@@ -67,6 +75,7 @@ from .commands.experiments import experiments as experiments_group
|
|
|
67
75
|
from .commands.configure import register_command as register_configure_command
|
|
68
76
|
from .commands.serve import register_command as register_serve_command
|
|
69
77
|
from .commands.mcp import register_command as register_mcp_command
|
|
78
|
+
from .commands.scaffold import scaffold as scaffold_command
|
|
70
79
|
|
|
71
80
|
register_schema_commands(schema)
|
|
72
81
|
register_db_commands(db)
|
|
@@ -77,6 +86,7 @@ register_configure_command(cli)
|
|
|
77
86
|
register_serve_command(cli)
|
|
78
87
|
register_mcp_command(cli)
|
|
79
88
|
cli.add_command(experiments_group)
|
|
89
|
+
cli.add_command(scaffold_command)
|
|
80
90
|
|
|
81
91
|
|
|
82
92
|
def main():
|
rem/config.py
CHANGED
|
@@ -15,7 +15,7 @@ File Format (~/.rem/config.yaml):
|
|
|
15
15
|
pool_max_size: 20
|
|
16
16
|
|
|
17
17
|
llm:
|
|
18
|
-
default_model:
|
|
18
|
+
default_model: openai:gpt-4.1
|
|
19
19
|
openai_api_key: sk-...
|
|
20
20
|
anthropic_api_key: sk-ant-...
|
|
21
21
|
|
|
@@ -216,7 +216,7 @@ def get_default_config() -> dict[str, Any]:
|
|
|
216
216
|
"pool_max_size": 20,
|
|
217
217
|
},
|
|
218
218
|
"llm": {
|
|
219
|
-
"default_model": "
|
|
219
|
+
"default_model": "openai:gpt-4.1",
|
|
220
220
|
"default_temperature": 0.5,
|
|
221
221
|
# API keys will be prompted for in wizard
|
|
222
222
|
# "openai_api_key": "",
|
rem/models/core/core_model.py
CHANGED
|
@@ -52,7 +52,13 @@ class CoreModel(BaseModel):
|
|
|
52
52
|
default=None, description="Tenant identifier for multi-tenancy isolation"
|
|
53
53
|
)
|
|
54
54
|
user_id: Optional[str] = Field(
|
|
55
|
-
default=None,
|
|
55
|
+
default=None,
|
|
56
|
+
description=(
|
|
57
|
+
"Owner user identifier (tenant-scoped). This is a VARCHAR(256), not a UUID, "
|
|
58
|
+
"to allow flexibility for external identity providers. Typically generated as "
|
|
59
|
+
"a hash of the user's email address. In future, other strong unique claims "
|
|
60
|
+
"(e.g., OAuth sub, verified phone) could also be used for generation."
|
|
61
|
+
),
|
|
56
62
|
)
|
|
57
63
|
graph_edges: list[dict] = Field(
|
|
58
64
|
default_factory=list,
|
rem/models/entities/__init__.py
CHANGED
|
@@ -5,6 +5,9 @@ Core entity types for the REM system:
|
|
|
5
5
|
- Resources: Base content units (documents, conversations, artifacts)
|
|
6
6
|
- ImageResources: Image-specific resources with CLIP embeddings
|
|
7
7
|
- Messages: Communication content
|
|
8
|
+
- Sessions: Conversation sessions (normal or evaluation mode)
|
|
9
|
+
- SharedSessions: Session sharing between users for collaboration
|
|
10
|
+
- Feedback: User feedback on messages/sessions with trace integration
|
|
8
11
|
- Users: User entities
|
|
9
12
|
- Files: File metadata and tracking
|
|
10
13
|
- Moments: Temporal narratives (meetings, coding sessions, conversations)
|
|
@@ -19,6 +22,8 @@ All entities inherit from CoreModel and support:
|
|
|
19
22
|
- Natural language labels for conversational queries
|
|
20
23
|
"""
|
|
21
24
|
|
|
25
|
+
from .domain_resource import DomainResource
|
|
26
|
+
from .feedback import Feedback, FeedbackCategory
|
|
22
27
|
from .file import File
|
|
23
28
|
from .image_resource import ImageResource
|
|
24
29
|
from .message import Message
|
|
@@ -27,12 +32,28 @@ from .ontology import Ontology
|
|
|
27
32
|
from .ontology_config import OntologyConfig
|
|
28
33
|
from .resource import Resource
|
|
29
34
|
from .schema import Schema
|
|
35
|
+
from .session import Session, SessionMode
|
|
36
|
+
from .shared_session import (
|
|
37
|
+
SharedSession,
|
|
38
|
+
SharedSessionCreate,
|
|
39
|
+
SharedWithMeResponse,
|
|
40
|
+
SharedWithMeSummary,
|
|
41
|
+
)
|
|
30
42
|
from .user import User, UserTier
|
|
31
43
|
|
|
32
44
|
__all__ = [
|
|
33
45
|
"Resource",
|
|
46
|
+
"DomainResource",
|
|
34
47
|
"ImageResource",
|
|
35
48
|
"Message",
|
|
49
|
+
"Session",
|
|
50
|
+
"SessionMode",
|
|
51
|
+
"SharedSession",
|
|
52
|
+
"SharedSessionCreate",
|
|
53
|
+
"SharedWithMeResponse",
|
|
54
|
+
"SharedWithMeSummary",
|
|
55
|
+
"Feedback",
|
|
56
|
+
"FeedbackCategory",
|
|
36
57
|
"User",
|
|
37
58
|
"UserTier",
|
|
38
59
|
"File",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DomainResource - Curated internal knowledge in REM.
|
|
3
|
+
|
|
4
|
+
DomainResources are a specialized subclass of Resource for storing curated,
|
|
5
|
+
domain-specific internal knowledge that is not part of general knowledge.
|
|
6
|
+
This includes proprietary information, internal documentation, institutional
|
|
7
|
+
knowledge, and other content that requires more careful curation.
|
|
8
|
+
|
|
9
|
+
Key Differences from Resource:
|
|
10
|
+
- Intended for curated, internal knowledge (not raw ingested content)
|
|
11
|
+
- Higher quality bar - content is reviewed/vetted before ingestion
|
|
12
|
+
- May contain proprietary or sensitive information
|
|
13
|
+
- Subject to different retention/governance policies
|
|
14
|
+
|
|
15
|
+
Use Cases:
|
|
16
|
+
- Internal documentation and procedures
|
|
17
|
+
- Proprietary research and analysis
|
|
18
|
+
- Institutional knowledge bases
|
|
19
|
+
- Domain-specific ontologies and taxonomies
|
|
20
|
+
- Curated best practices and guidelines
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .resource import Resource
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DomainResource(Resource):
|
|
27
|
+
"""
|
|
28
|
+
Curated domain-specific knowledge resource.
|
|
29
|
+
|
|
30
|
+
Inherits all fields from Resource but stored in a separate table
|
|
31
|
+
(domain_resources) to distinguish curated internal knowledge from
|
|
32
|
+
general ingested content.
|
|
33
|
+
|
|
34
|
+
The schema is identical to Resource, allowing seamless migration
|
|
35
|
+
of content between tables as curation status changes.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
pass
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Feedback - User feedback on chat messages and sessions.
|
|
3
|
+
|
|
4
|
+
Feedback allows users to rate and categorize responses, providing
|
|
5
|
+
data for evaluation and model improvement. Feedback can be attached
|
|
6
|
+
to specific messages or entire sessions.
|
|
7
|
+
|
|
8
|
+
Trace Integration:
|
|
9
|
+
- Feedback references trace_id/span_id for OTEL/Phoenix integration
|
|
10
|
+
- Can attach annotations to Phoenix spans for unified observability
|
|
11
|
+
|
|
12
|
+
Predefined Categories (system-defined, extensible):
|
|
13
|
+
- INCOMPLETE: Response lacks expected information
|
|
14
|
+
- INACCURATE: Response contains factual errors
|
|
15
|
+
- POOR_TONE: Inappropriate or unprofessional tone
|
|
16
|
+
- OFF_TOPIC: Response doesn't address the question
|
|
17
|
+
- TOO_VERBOSE: Unnecessarily long response
|
|
18
|
+
- TOO_BRIEF: Insufficiently detailed response
|
|
19
|
+
- HELPFUL: Positive feedback marker
|
|
20
|
+
- EXCELLENT: Exceptionally good response
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from enum import Enum
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
from pydantic import Field
|
|
27
|
+
|
|
28
|
+
from ..core import CoreModel
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FeedbackCategory(str, Enum):
|
|
32
|
+
"""Predefined feedback categories (system-defined)."""
|
|
33
|
+
|
|
34
|
+
# Negative categories
|
|
35
|
+
INCOMPLETE = "incomplete"
|
|
36
|
+
INACCURATE = "inaccurate"
|
|
37
|
+
POOR_TONE = "poor_tone"
|
|
38
|
+
OFF_TOPIC = "off_topic"
|
|
39
|
+
TOO_VERBOSE = "too_verbose"
|
|
40
|
+
TOO_BRIEF = "too_brief"
|
|
41
|
+
CONFUSING = "confusing"
|
|
42
|
+
UNSAFE = "unsafe"
|
|
43
|
+
|
|
44
|
+
# Positive categories
|
|
45
|
+
HELPFUL = "helpful"
|
|
46
|
+
EXCELLENT = "excellent"
|
|
47
|
+
ACCURATE = "accurate"
|
|
48
|
+
WELL_WRITTEN = "well_written"
|
|
49
|
+
|
|
50
|
+
# Neutral/Other
|
|
51
|
+
OTHER = "other"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Feedback(CoreModel):
|
|
55
|
+
"""
|
|
56
|
+
User feedback on a message or session.
|
|
57
|
+
|
|
58
|
+
Captures structured feedback including:
|
|
59
|
+
- Rating (1-5 scale or thumbs up/down)
|
|
60
|
+
- Categories (predefined or custom)
|
|
61
|
+
- Free-text comment
|
|
62
|
+
- Trace reference for OTEL/Phoenix integration
|
|
63
|
+
|
|
64
|
+
The feedback can be attached to:
|
|
65
|
+
- A specific message (message_id set)
|
|
66
|
+
- An entire session (session_id set, message_id null)
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
# Target reference (at least one required)
|
|
70
|
+
session_id: str = Field(
|
|
71
|
+
...,
|
|
72
|
+
description="Session ID this feedback relates to",
|
|
73
|
+
)
|
|
74
|
+
message_id: str | None = Field(
|
|
75
|
+
default=None,
|
|
76
|
+
description="Specific message ID (null for session-level feedback)",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Rating (flexible: 1-5, or -1/1 for thumbs)
|
|
80
|
+
rating: int | None = Field(
|
|
81
|
+
default=None,
|
|
82
|
+
ge=-1,
|
|
83
|
+
le=5,
|
|
84
|
+
description="Rating: -1 (thumbs down), 1 (thumbs up), or 1-5 scale",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Categories (can select multiple)
|
|
88
|
+
categories: list[str] = Field(
|
|
89
|
+
default_factory=list,
|
|
90
|
+
description="Selected feedback categories (from FeedbackCategory or custom)",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Free-text comment
|
|
94
|
+
comment: str | None = Field(
|
|
95
|
+
default=None,
|
|
96
|
+
description="Optional free-text feedback comment",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# Trace reference for OTEL/Phoenix integration
|
|
100
|
+
trace_id: str | None = Field(
|
|
101
|
+
default=None,
|
|
102
|
+
description="OTEL trace ID for linking to observability",
|
|
103
|
+
)
|
|
104
|
+
span_id: str | None = Field(
|
|
105
|
+
default=None,
|
|
106
|
+
description="OTEL span ID for specific span feedback",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Phoenix annotation status
|
|
110
|
+
phoenix_synced: bool = Field(
|
|
111
|
+
default=False,
|
|
112
|
+
description="Whether feedback has been synced to Phoenix as annotation",
|
|
113
|
+
)
|
|
114
|
+
phoenix_annotation_id: str | None = Field(
|
|
115
|
+
default=None,
|
|
116
|
+
description="Phoenix annotation ID after sync",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Annotator info
|
|
120
|
+
annotator_kind: str = Field(
|
|
121
|
+
default="HUMAN",
|
|
122
|
+
description="Annotator type: HUMAN, LLM, CODE",
|
|
123
|
+
)
|
rem/models/entities/message.py
CHANGED
|
@@ -6,6 +6,11 @@ that can be grouped into conversations or moments.
|
|
|
6
6
|
|
|
7
7
|
Messages are simpler than Resources but share the same graph connectivity
|
|
8
8
|
through CoreModel inheritance.
|
|
9
|
+
|
|
10
|
+
Trace Integration:
|
|
11
|
+
- trace_id: OTEL trace ID for linking to observability
|
|
12
|
+
- span_id: OTEL span ID for specific span reference
|
|
13
|
+
- These enable feedback to be attached to Phoenix annotations
|
|
9
14
|
"""
|
|
10
15
|
|
|
11
16
|
from pydantic import Field
|
|
@@ -19,6 +24,9 @@ class Message(CoreModel):
|
|
|
19
24
|
|
|
20
25
|
Represents individual messages in conversations, chats, or other
|
|
21
26
|
communication contexts. Tenant isolation is provided via CoreModel.tenant_id field.
|
|
27
|
+
|
|
28
|
+
Trace fields (trace_id, span_id) enable integration with OTEL/Phoenix
|
|
29
|
+
for observability and feedback annotation.
|
|
22
30
|
"""
|
|
23
31
|
|
|
24
32
|
content: str = Field(
|
|
@@ -27,9 +35,30 @@ class Message(CoreModel):
|
|
|
27
35
|
)
|
|
28
36
|
message_type: str | None = Field(
|
|
29
37
|
default=None,
|
|
30
|
-
description="Message type e.g role",
|
|
38
|
+
description="Message type e.g. role: 'user', 'assistant', 'system', 'tool'",
|
|
31
39
|
)
|
|
32
40
|
session_id: str | None = Field(
|
|
33
41
|
default=None,
|
|
34
42
|
description="Session identifier for tracking message context",
|
|
35
43
|
)
|
|
44
|
+
prompt: str | None = Field(
|
|
45
|
+
default=None,
|
|
46
|
+
description="Custom prompt used for this message (if overridden from default)",
|
|
47
|
+
)
|
|
48
|
+
model: str | None = Field(
|
|
49
|
+
default=None,
|
|
50
|
+
description="Model used for generating this message (provider:model format)",
|
|
51
|
+
)
|
|
52
|
+
token_count: int | None = Field(
|
|
53
|
+
default=None,
|
|
54
|
+
description="Token count for this message",
|
|
55
|
+
)
|
|
56
|
+
# OTEL/Phoenix trace integration
|
|
57
|
+
trace_id: str | None = Field(
|
|
58
|
+
default=None,
|
|
59
|
+
description="OTEL trace ID for observability integration",
|
|
60
|
+
)
|
|
61
|
+
span_id: str | None = Field(
|
|
62
|
+
default=None,
|
|
63
|
+
description="OTEL span ID for specific span reference",
|
|
64
|
+
)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session - Conversation sessions in REM.
|
|
3
|
+
|
|
4
|
+
Sessions group related messages together and can have different modes:
|
|
5
|
+
- normal: Standard conversation session
|
|
6
|
+
- evaluation: For LLM evaluation, stores original trace and overridden settings
|
|
7
|
+
|
|
8
|
+
Sessions allow overriding settings like model, temperature, and custom prompts
|
|
9
|
+
for evaluation and experimentation purposes.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from enum import Enum
|
|
13
|
+
|
|
14
|
+
from pydantic import Field
|
|
15
|
+
|
|
16
|
+
from ..core import CoreModel
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SessionMode(str, Enum):
|
|
20
|
+
"""Session mode types."""
|
|
21
|
+
|
|
22
|
+
NORMAL = "normal"
|
|
23
|
+
EVALUATION = "evaluation"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Session(CoreModel):
|
|
27
|
+
"""
|
|
28
|
+
Conversation session container.
|
|
29
|
+
|
|
30
|
+
Groups messages together and supports different modes for normal conversations
|
|
31
|
+
and evaluation/experimentation scenarios.
|
|
32
|
+
|
|
33
|
+
For evaluation sessions, stores:
|
|
34
|
+
- original_trace_id: Reference to the original session being evaluated
|
|
35
|
+
- settings_overrides: Model, temperature, prompt overrides
|
|
36
|
+
- prompt: Custom prompt being tested
|
|
37
|
+
|
|
38
|
+
Default sessions are lightweight - just a session_id on messages.
|
|
39
|
+
Special sessions store additional metadata for experiments.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
name: str = Field(
|
|
43
|
+
...,
|
|
44
|
+
description="Session name/identifier",
|
|
45
|
+
json_schema_extra={"entity_key": True},
|
|
46
|
+
)
|
|
47
|
+
mode: SessionMode = Field(
|
|
48
|
+
default=SessionMode.NORMAL,
|
|
49
|
+
description="Session mode: 'normal' or 'evaluation'",
|
|
50
|
+
)
|
|
51
|
+
description: str | None = Field(
|
|
52
|
+
default=None,
|
|
53
|
+
description="Optional session description",
|
|
54
|
+
)
|
|
55
|
+
# Evaluation-specific fields
|
|
56
|
+
original_trace_id: str | None = Field(
|
|
57
|
+
default=None,
|
|
58
|
+
description="For evaluation mode: ID of the original session/trace being evaluated",
|
|
59
|
+
)
|
|
60
|
+
settings_overrides: dict | None = Field(
|
|
61
|
+
default=None,
|
|
62
|
+
description="Settings overrides (model, temperature, max_tokens, system_prompt)",
|
|
63
|
+
)
|
|
64
|
+
prompt: str | None = Field(
|
|
65
|
+
default=None,
|
|
66
|
+
description="Custom prompt for this session (can override agent prompt)",
|
|
67
|
+
)
|
|
68
|
+
# Agent context
|
|
69
|
+
agent_schema_uri: str | None = Field(
|
|
70
|
+
default=None,
|
|
71
|
+
description="Agent schema used for this session",
|
|
72
|
+
)
|
|
73
|
+
# Summary stats (updated as session progresses)
|
|
74
|
+
message_count: int = Field(
|
|
75
|
+
default=0,
|
|
76
|
+
description="Number of messages in this session",
|
|
77
|
+
)
|
|
78
|
+
total_tokens: int | None = Field(
|
|
79
|
+
default=None,
|
|
80
|
+
description="Total tokens used in this session",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
model_config = {"use_enum_values": True}
|