prme 0.15.0__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.
- prme/__init__.py +317 -0
- prme/_temporal.py +9 -0
- prme/api/__init__.py +20 -0
- prme/api/__main__.py +64 -0
- prme/api/app.py +106 -0
- prme/api/models.py +584 -0
- prme/api/routes.py +1389 -0
- prme/api/server.py +153 -0
- prme/cli.py +1667 -0
- prme/client.py +1135 -0
- prme/config.py +1249 -0
- prme/config_audit.py +318 -0
- prme/epistemic/__init__.py +16 -0
- prme/epistemic/inference.py +99 -0
- prme/epistemic/matrix.py +135 -0
- prme/epistemic/migration.py +160 -0
- prme/ingestion/__init__.py +45 -0
- prme/ingestion/claim_merge.py +122 -0
- prme/ingestion/entity_merge.py +158 -0
- prme/ingestion/entity_references.py +102 -0
- prme/ingestion/errors.py +123 -0
- prme/ingestion/extraction.py +1661 -0
- prme/ingestion/graph_writer.py +224 -0
- prme/ingestion/grounding.py +594 -0
- prme/ingestion/novelty.py +181 -0
- prme/ingestion/pipeline.py +1752 -0
- prme/ingestion/planning.py +225 -0
- prme/ingestion/resolution.py +517 -0
- prme/ingestion/schema.py +301 -0
- prme/ingestion/supersedence.py +316 -0
- prme/ingestion/temporal.py +35 -0
- prme/integrations/__init__.py +11 -0
- prme/integrations/_chat_history.py +131 -0
- prme/integrations/coding.py +316 -0
- prme/integrations/coding_server.py +28 -0
- prme/integrations/langchain.py +287 -0
- prme/integrations/llamaindex.py +334 -0
- prme/integrations/product_candidates.py +211 -0
- prme/integrations/typesafe.py +579 -0
- prme/mcp/__init__.py +22 -0
- prme/mcp/__main__.py +5 -0
- prme/mcp/server.py +1889 -0
- prme/model_runtime/__init__.py +5 -0
- prme/model_runtime/generation.py +109 -0
- prme/models/__init__.py +84 -0
- prme/models/aggregation.py +308 -0
- prme/models/base.py +38 -0
- prme/models/consolidation.py +217 -0
- prme/models/credit.py +97 -0
- prme/models/derivation.py +194 -0
- prme/models/direct_store.py +54 -0
- prme/models/edges.py +52 -0
- prme/models/entity_identity.py +19 -0
- prme/models/events.py +65 -0
- prme/models/extraction.py +152 -0
- prme/models/extraction_work.py +46 -0
- prme/models/learning.py +547 -0
- prme/models/nodes.py +109 -0
- prme/models/owner_reference.py +32 -0
- prme/models/processing.py +82 -0
- prme/models/profile.py +166 -0
- prme/models/provenance.py +38 -0
- prme/models/relevance.py +730 -0
- prme/models/speaker.py +136 -0
- prme/models/temporal.py +193 -0
- prme/models/value_bindings.py +368 -0
- prme/organizer/__init__.py +50 -0
- prme/organizer/alias_resolution.py +412 -0
- prme/organizer/consolidation.py +589 -0
- prme/organizer/contradiction.py +94 -0
- prme/organizer/decay.py +178 -0
- prme/organizer/deduplication.py +296 -0
- prme/organizer/jobs.py +869 -0
- prme/organizer/maintenance.py +323 -0
- prme/organizer/merge_policy.py +36 -0
- prme/organizer/models.py +57 -0
- prme/organizer/oscillation.py +174 -0
- prme/organizer/profiles.py +43 -0
- prme/organizer/summarization.py +665 -0
- prme/py.typed +1 -0
- prme/quality/__init__.py +23 -0
- prme/quality/feedback.py +116 -0
- prme/quality/metrics.py +82 -0
- prme/quality/tuner.py +198 -0
- prme/retrieval/__init__.py +127 -0
- prme/retrieval/abstention.py +140 -0
- prme/retrieval/aggregation.py +511 -0
- prme/retrieval/aggregation_planning.py +165 -0
- prme/retrieval/answerability.py +547 -0
- prme/retrieval/candidates.py +566 -0
- prme/retrieval/claim_verification.py +1077 -0
- prme/retrieval/config.py +787 -0
- prme/retrieval/context_formatter.py +1014 -0
- prme/retrieval/credit.py +151 -0
- prme/retrieval/episode_context.py +194 -0
- prme/retrieval/evidence_context.py +341 -0
- prme/retrieval/execution.py +102 -0
- prme/retrieval/filtering.py +175 -0
- prme/retrieval/full_learning.py +275 -0
- prme/retrieval/learning.py +265 -0
- prme/retrieval/models.py +767 -0
- prme/retrieval/packing.py +1026 -0
- prme/retrieval/pipeline.py +1391 -0
- prme/retrieval/query_analysis.py +382 -0
- prme/retrieval/ranking_adjustments.py +19 -0
- prme/retrieval/reformulation.py +214 -0
- prme/retrieval/reranker.py +203 -0
- prme/retrieval/scope.py +30 -0
- prme/retrieval/scoring.py +984 -0
- prme/retrieval/selection.py +151 -0
- prme/retrieval/session_context.py +259 -0
- prme/retrieval/snapshots.py +251 -0
- prme/retrieval/temporal.py +293 -0
- prme/retrieval/temporal_relation_models.py +99 -0
- prme/retrieval/temporal_relation_providers.py +554 -0
- prme/retrieval/temporal_relations.py +677 -0
- prme/retrieval/time.py +12 -0
- prme/retrieval/tokenization.py +15 -0
- prme/storage/__init__.py +25 -0
- prme/storage/_snapshot_json.py +117 -0
- prme/storage/_threading.py +41 -0
- prme/storage/alias_proposal.py +657 -0
- prme/storage/alias_review.py +616 -0
- prme/storage/blobs.py +90 -0
- prme/storage/citations.py +117 -0
- prme/storage/condition_evaluation.py +425 -0
- prme/storage/consolidation_publication.py +762 -0
- prme/storage/consolidation_retirement.py +163 -0
- prme/storage/derivation.py +232 -0
- prme/storage/derivation_registry.py +154 -0
- prme/storage/derivation_staging.py +57 -0
- prme/storage/duckpgq_graph.py +2020 -0
- prme/storage/durable_queue.py +97 -0
- prme/storage/embedding.py +512 -0
- prme/storage/encryption.py +460 -0
- prme/storage/engine.py +4360 -0
- prme/storage/event_store.py +730 -0
- prme/storage/extraction_work.py +388 -0
- prme/storage/fast_ingest.py +165 -0
- prme/storage/graph_store.py +573 -0
- prme/storage/index_eviction.py +48 -0
- prme/storage/lexical_index.py +873 -0
- prme/storage/lifecycle.py +232 -0
- prme/storage/metadata.py +30 -0
- prme/storage/namespace_identity.py +33 -0
- prme/storage/organizer_merge.py +216 -0
- prme/storage/oscillation_penalty.py +418 -0
- prme/storage/pack_manifest.py +118 -0
- prme/storage/pack_tools.py +438 -0
- prme/storage/pg/__init__.py +26 -0
- prme/storage/pg/event_store.py +600 -0
- prme/storage/pg/graph_store.py +1494 -0
- prme/storage/pg/lexical_index.py +191 -0
- prme/storage/pg/namespace.py +131 -0
- prme/storage/pg/pool.py +35 -0
- prme/storage/pg/schema.py +261 -0
- prme/storage/pg/vector_index.py +240 -0
- prme/storage/pg/vector_sql.py +44 -0
- prme/storage/pg/workspace_catalog.py +75 -0
- prme/storage/profile_collection.py +272 -0
- prme/storage/profile_publication.py +270 -0
- prme/storage/profile_registry.py +292 -0
- prme/storage/profile_retirement.py +126 -0
- prme/storage/profile_work.py +539 -0
- prme/storage/provenance.py +101 -0
- prme/storage/ranking_profiles.py +284 -0
- prme/storage/reinforcement.py +281 -0
- prme/storage/relevance.py +201 -0
- prme/storage/retention.py +369 -0
- prme/storage/schema.py +575 -0
- prme/storage/supersedence.py +261 -0
- prme/storage/transition_evidence.py +48 -0
- prme/storage/vector_index.py +872 -0
- prme/storage/write_queue.py +271 -0
- prme/types.py +301 -0
- prme/vision/__init__.py +44 -0
- prme/vision/describe.py +71 -0
- prme/vision/errors.py +33 -0
- prme/vision/frames.py +343 -0
- prme/vision/keyframes.py +158 -0
- prme/vision/observe.py +375 -0
- prme/vision/provider.py +98 -0
- prme/vision/repeat.py +44 -0
- prme/workspace.py +469 -0
- prme-0.15.0.dist-info/METADATA +329 -0
- prme-0.15.0.dist-info/RECORD +188 -0
- prme-0.15.0.dist-info/WHEEL +4 -0
- prme-0.15.0.dist-info/entry_points.txt +4 -0
prme/__init__.py
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""PRME - Portable Relational Memory Engine.
|
|
2
|
+
|
|
3
|
+
A local-first, embeddable memory substrate for LLM-powered systems.
|
|
4
|
+
Combines event sourcing, graph-based relational modeling, hybrid retrieval,
|
|
5
|
+
and explicit or opportunistic memory reorganization.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "0.15.0"
|
|
9
|
+
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from prme.workspace import (
|
|
14
|
+
MemoryWorkspace,
|
|
15
|
+
NamespaceInfo,
|
|
16
|
+
NamespaceMemory,
|
|
17
|
+
WorkspaceError,
|
|
18
|
+
)
|
|
19
|
+
from prme.client import MemoryClient, config_from_directory, config_from_pack
|
|
20
|
+
from prme.ingestion.pipeline import IngestionPipeline
|
|
21
|
+
from prme.retrieval.models import RetrievalResponse
|
|
22
|
+
from prme.retrieval.pipeline import RetrievalPipeline
|
|
23
|
+
|
|
24
|
+
from prme.config import PRMEConfig
|
|
25
|
+
from prme.config_audit import (
|
|
26
|
+
HypothesisAudit as HypothesisAudit,
|
|
27
|
+
HypothesisSetting as HypothesisSetting,
|
|
28
|
+
audit_hypotheses as audit_hypotheses,
|
|
29
|
+
)
|
|
30
|
+
from prme.ingestion.errors import ExtractionError, MaterializationError
|
|
31
|
+
from prme.models.aggregation import (
|
|
32
|
+
AssertionAggregation,
|
|
33
|
+
AssertionGroup,
|
|
34
|
+
AssertionQuery,
|
|
35
|
+
QuantityAggregation,
|
|
36
|
+
QuantityAggregationPlan,
|
|
37
|
+
QuantityAggregationQuery,
|
|
38
|
+
QuantityGroup,
|
|
39
|
+
QuantitySample,
|
|
40
|
+
PlannedQuantityAggregation,
|
|
41
|
+
)
|
|
42
|
+
from prme.models.temporal import (
|
|
43
|
+
AssertionState,
|
|
44
|
+
AssertionStateConflict,
|
|
45
|
+
AssertionStateEntry,
|
|
46
|
+
AssertionStateHistoricalCoverage,
|
|
47
|
+
AssertionStateQuery,
|
|
48
|
+
AssertionStateValue,
|
|
49
|
+
)
|
|
50
|
+
from prme.models.processing import (
|
|
51
|
+
FastIngestItem,
|
|
52
|
+
ProcessingResult,
|
|
53
|
+
ProcessingStatus,
|
|
54
|
+
StoreReceipt,
|
|
55
|
+
)
|
|
56
|
+
from prme.models.value_bindings import (
|
|
57
|
+
MemoryValueBinding,
|
|
58
|
+
RetrievedValueBinding,
|
|
59
|
+
ToolArgumentBindingUse,
|
|
60
|
+
ToolArgumentReplacement,
|
|
61
|
+
ToolArgumentResolution,
|
|
62
|
+
)
|
|
63
|
+
from prme.storage.fast_ingest import FastIngestConflict
|
|
64
|
+
from prme.storage.alias_review import (
|
|
65
|
+
AliasProposalDecision,
|
|
66
|
+
AliasProposalInboxItem,
|
|
67
|
+
AliasProposalReviewConflict,
|
|
68
|
+
AliasProposalReviewRecord,
|
|
69
|
+
AliasProposalReviewResult,
|
|
70
|
+
AliasProposalStatus,
|
|
71
|
+
StaleAliasProposal,
|
|
72
|
+
)
|
|
73
|
+
from prme.integrations.product_candidates import (
|
|
74
|
+
PRODUCT_CANDIDATE_POLICY,
|
|
75
|
+
ProductAlignmentCandidate,
|
|
76
|
+
ProductCandidateEntity,
|
|
77
|
+
rank_product_alignment_candidates,
|
|
78
|
+
)
|
|
79
|
+
from prme.models.credit import ContextAblation, ContextPresenceCredit
|
|
80
|
+
from prme.models.profile import (
|
|
81
|
+
StaleProfileError,
|
|
82
|
+
ProfileJobStatus,
|
|
83
|
+
ProfileProcessingResult,
|
|
84
|
+
ProfileCollectionResult,
|
|
85
|
+
)
|
|
86
|
+
from prme.models.relevance import (
|
|
87
|
+
AnswerCitationRecord,
|
|
88
|
+
AnswerCitationSubmission,
|
|
89
|
+
RelevanceRecord,
|
|
90
|
+
RelevanceSubmission,
|
|
91
|
+
RetrievalReceipt,
|
|
92
|
+
)
|
|
93
|
+
from prme.models.provenance import NodeProvenance, OperationAuditRecord
|
|
94
|
+
from prme.models.learning import (
|
|
95
|
+
FullRetrievalEvaluation,
|
|
96
|
+
FullRetrievalEvaluationConfig,
|
|
97
|
+
FullRetrievalQueryResult,
|
|
98
|
+
FullRetrievalTrial,
|
|
99
|
+
LearningConfig,
|
|
100
|
+
LearningEvaluation,
|
|
101
|
+
RankingMultipliers,
|
|
102
|
+
RankingProfile,
|
|
103
|
+
RankingProfileApplication,
|
|
104
|
+
RankingProfileState,
|
|
105
|
+
RankingProfileStatus,
|
|
106
|
+
)
|
|
107
|
+
from prme.models.extraction import ExtractionRecord
|
|
108
|
+
from prme.models.extraction_work import ExtractionStatus, ExtractionProcessingResult
|
|
109
|
+
from prme.storage.engine import MemoryEngine
|
|
110
|
+
from prme.storage.namespace_identity import NamespaceIdentityError
|
|
111
|
+
from prme.storage.ranking_profiles import StaleRankingProfileError
|
|
112
|
+
from prme.storage.embedding import (
|
|
113
|
+
CachedEmbeddingProvider,
|
|
114
|
+
EmbeddingProvider,
|
|
115
|
+
QueryEmbeddingProvider,
|
|
116
|
+
)
|
|
117
|
+
from prme.retrieval.credit import ablate_context, assess_context_presence
|
|
118
|
+
from prme.retrieval.answerability import (
|
|
119
|
+
AnswerabilityAction,
|
|
120
|
+
AnswerabilityAssessment,
|
|
121
|
+
AnswerabilityConfig,
|
|
122
|
+
AnswerabilityError,
|
|
123
|
+
AnswerabilityEvaluator,
|
|
124
|
+
AnswerabilityRequirement,
|
|
125
|
+
AnswerabilityStatus,
|
|
126
|
+
AnswerabilityVerdict,
|
|
127
|
+
assess_answerability,
|
|
128
|
+
)
|
|
129
|
+
from prme.retrieval.claim_verification import (
|
|
130
|
+
ClaimEvidence,
|
|
131
|
+
ClaimVerification,
|
|
132
|
+
ClaimVerificationConfig,
|
|
133
|
+
ClaimVerificationDecisionBasis,
|
|
134
|
+
ClaimVerificationError,
|
|
135
|
+
ClaimVerificationLimitation,
|
|
136
|
+
ClaimVerificationStatus,
|
|
137
|
+
ClaimVerifier,
|
|
138
|
+
EvidenceGroupScore,
|
|
139
|
+
LocalizedEvidenceAssessment,
|
|
140
|
+
)
|
|
141
|
+
from prme.retrieval.full_learning import evaluate_full_retrieval
|
|
142
|
+
from prme.retrieval.temporal_relation_models import TemporalRelationMetadata
|
|
143
|
+
from prme.retrieval.temporal_relations import TemporalRelationConfig
|
|
144
|
+
from prme.types import (
|
|
145
|
+
ConditionEvaluationMethod,
|
|
146
|
+
ConditionState,
|
|
147
|
+
DECAY_LAMBDAS,
|
|
148
|
+
DEFAULT_DECAY_PROFILE_MAPPING,
|
|
149
|
+
DecayProfile,
|
|
150
|
+
EdgeType,
|
|
151
|
+
EpistemicType,
|
|
152
|
+
LifecycleState,
|
|
153
|
+
NodeType,
|
|
154
|
+
RetrievalMode,
|
|
155
|
+
Scope,
|
|
156
|
+
SourceType,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def __getattr__(name: str):
|
|
161
|
+
"""Lazy imports for heavy modules to avoid circular import chains."""
|
|
162
|
+
if name in {
|
|
163
|
+
"MemoryWorkspace",
|
|
164
|
+
"NamespaceInfo",
|
|
165
|
+
"NamespaceMemory",
|
|
166
|
+
"WorkspaceError",
|
|
167
|
+
}:
|
|
168
|
+
from prme import workspace
|
|
169
|
+
|
|
170
|
+
return getattr(workspace, name)
|
|
171
|
+
if name == "MemoryClient":
|
|
172
|
+
from prme.client import MemoryClient
|
|
173
|
+
|
|
174
|
+
return MemoryClient
|
|
175
|
+
if name == "config_from_directory":
|
|
176
|
+
from prme.client import config_from_directory
|
|
177
|
+
|
|
178
|
+
return config_from_directory
|
|
179
|
+
if name == "config_from_pack":
|
|
180
|
+
from prme.client import config_from_pack
|
|
181
|
+
|
|
182
|
+
return config_from_pack
|
|
183
|
+
if name == "IngestionPipeline":
|
|
184
|
+
from prme.ingestion.pipeline import IngestionPipeline
|
|
185
|
+
|
|
186
|
+
return IngestionPipeline
|
|
187
|
+
if name == "RetrievalResponse":
|
|
188
|
+
from prme.retrieval.models import RetrievalResponse
|
|
189
|
+
|
|
190
|
+
return RetrievalResponse
|
|
191
|
+
if name == "RetrievalPipeline":
|
|
192
|
+
from prme.retrieval.pipeline import RetrievalPipeline
|
|
193
|
+
|
|
194
|
+
return RetrievalPipeline
|
|
195
|
+
raise AttributeError(f"module 'prme' has no attribute {name!r}")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
__all__ = [
|
|
199
|
+
"AnswerCitationRecord",
|
|
200
|
+
"AnswerCitationSubmission",
|
|
201
|
+
"AliasProposalDecision",
|
|
202
|
+
"AliasProposalInboxItem",
|
|
203
|
+
"AliasProposalReviewConflict",
|
|
204
|
+
"AliasProposalReviewRecord",
|
|
205
|
+
"AliasProposalReviewResult",
|
|
206
|
+
"AliasProposalStatus",
|
|
207
|
+
"AnswerabilityAction",
|
|
208
|
+
"AnswerabilityAssessment",
|
|
209
|
+
"AnswerabilityConfig",
|
|
210
|
+
"AnswerabilityError",
|
|
211
|
+
"AnswerabilityEvaluator",
|
|
212
|
+
"AnswerabilityRequirement",
|
|
213
|
+
"AnswerabilityStatus",
|
|
214
|
+
"AnswerabilityVerdict",
|
|
215
|
+
"AssertionAggregation",
|
|
216
|
+
"AssertionGroup",
|
|
217
|
+
"AssertionQuery",
|
|
218
|
+
"AssertionState",
|
|
219
|
+
"AssertionStateConflict",
|
|
220
|
+
"AssertionStateEntry",
|
|
221
|
+
"AssertionStateHistoricalCoverage",
|
|
222
|
+
"AssertionStateQuery",
|
|
223
|
+
"AssertionStateValue",
|
|
224
|
+
"ClaimEvidence",
|
|
225
|
+
"ClaimVerification",
|
|
226
|
+
"ClaimVerificationConfig",
|
|
227
|
+
"ClaimVerificationDecisionBasis",
|
|
228
|
+
"ClaimVerificationError",
|
|
229
|
+
"ClaimVerificationLimitation",
|
|
230
|
+
"ClaimVerificationStatus",
|
|
231
|
+
"ClaimVerifier",
|
|
232
|
+
"LocalizedEvidenceAssessment",
|
|
233
|
+
"QuantityAggregation",
|
|
234
|
+
"QuantityAggregationPlan",
|
|
235
|
+
"QuantityAggregationQuery",
|
|
236
|
+
"QuantityGroup",
|
|
237
|
+
"QuantitySample",
|
|
238
|
+
"PlannedQuantityAggregation",
|
|
239
|
+
"ConditionEvaluationMethod",
|
|
240
|
+
"ConditionState",
|
|
241
|
+
"ContextAblation",
|
|
242
|
+
"ContextPresenceCredit",
|
|
243
|
+
"DECAY_LAMBDAS",
|
|
244
|
+
"DEFAULT_DECAY_PROFILE_MAPPING",
|
|
245
|
+
"DecayProfile",
|
|
246
|
+
"CachedEmbeddingProvider",
|
|
247
|
+
"EmbeddingProvider",
|
|
248
|
+
"QueryEmbeddingProvider",
|
|
249
|
+
"EdgeType",
|
|
250
|
+
"EpistemicType",
|
|
251
|
+
"EvidenceGroupScore",
|
|
252
|
+
"ExtractionError",
|
|
253
|
+
"ExtractionRecord",
|
|
254
|
+
"ExtractionStatus",
|
|
255
|
+
"ExtractionProcessingResult",
|
|
256
|
+
"FastIngestItem",
|
|
257
|
+
"FastIngestConflict",
|
|
258
|
+
"IngestionPipeline",
|
|
259
|
+
"LifecycleState",
|
|
260
|
+
"LearningConfig",
|
|
261
|
+
"LearningEvaluation",
|
|
262
|
+
"FullRetrievalEvaluation",
|
|
263
|
+
"FullRetrievalEvaluationConfig",
|
|
264
|
+
"FullRetrievalQueryResult",
|
|
265
|
+
"FullRetrievalTrial",
|
|
266
|
+
"MaterializationError",
|
|
267
|
+
"MemoryClient",
|
|
268
|
+
"MemoryEngine",
|
|
269
|
+
"MemoryValueBinding",
|
|
270
|
+
"MemoryWorkspace",
|
|
271
|
+
"NamespaceInfo",
|
|
272
|
+
"NamespaceMemory",
|
|
273
|
+
"NamespaceIdentityError",
|
|
274
|
+
"WorkspaceError",
|
|
275
|
+
"NodeType",
|
|
276
|
+
"NodeProvenance",
|
|
277
|
+
"OperationAuditRecord",
|
|
278
|
+
"PRMEConfig",
|
|
279
|
+
"ProcessingResult",
|
|
280
|
+
"ProcessingStatus",
|
|
281
|
+
"PRODUCT_CANDIDATE_POLICY",
|
|
282
|
+
"ProductAlignmentCandidate",
|
|
283
|
+
"ProductCandidateEntity",
|
|
284
|
+
"ProfileJobStatus",
|
|
285
|
+
"ProfileProcessingResult",
|
|
286
|
+
"ProfileCollectionResult",
|
|
287
|
+
"RetrievalPipeline",
|
|
288
|
+
"RetrievalResponse",
|
|
289
|
+
"RetrievalReceipt",
|
|
290
|
+
"RetrievedValueBinding",
|
|
291
|
+
"RetrievalMode",
|
|
292
|
+
"RankingMultipliers",
|
|
293
|
+
"RankingProfile",
|
|
294
|
+
"RankingProfileApplication",
|
|
295
|
+
"RankingProfileState",
|
|
296
|
+
"RankingProfileStatus",
|
|
297
|
+
"RelevanceSubmission",
|
|
298
|
+
"RelevanceRecord",
|
|
299
|
+
"Scope",
|
|
300
|
+
"SourceType",
|
|
301
|
+
"StaleProfileError",
|
|
302
|
+
"StaleAliasProposal",
|
|
303
|
+
"StaleRankingProfileError",
|
|
304
|
+
"StoreReceipt",
|
|
305
|
+
"TemporalRelationConfig",
|
|
306
|
+
"TemporalRelationMetadata",
|
|
307
|
+
"ToolArgumentBindingUse",
|
|
308
|
+
"ToolArgumentReplacement",
|
|
309
|
+
"ToolArgumentResolution",
|
|
310
|
+
"ablate_context",
|
|
311
|
+
"assess_context_presence",
|
|
312
|
+
"assess_answerability",
|
|
313
|
+
"evaluate_full_retrieval",
|
|
314
|
+
"rank_product_alignment_candidates",
|
|
315
|
+
"config_from_directory",
|
|
316
|
+
"config_from_pack",
|
|
317
|
+
]
|
prme/_temporal.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Guard PRME's entries into dateparser's process-wide mutable parser state."""
|
|
2
|
+
|
|
3
|
+
from threading import RLock
|
|
4
|
+
|
|
5
|
+
# Older supported dateparser versions share settings and lazy locale caches.
|
|
6
|
+
# Ingestion and retrieval can run on different MemoryClient/event-loop threads.
|
|
7
|
+
# Keep every PRME parse/search call in the same critical section; an independent
|
|
8
|
+
# lock per pipeline does not protect either shared settings or locale caches.
|
|
9
|
+
DATEPARSER_LOCK = RLock()
|
prme/api/__init__.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""PRME HTTP API layer (FastAPI).
|
|
2
|
+
|
|
3
|
+
Provides REST endpoints for store, retrieve, organize, and lifecycle
|
|
4
|
+
operations. The API is an optional dependency — install with:
|
|
5
|
+
|
|
6
|
+
pip install prme[api]
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
|
|
10
|
+
from prme.api.app import create_app
|
|
11
|
+
app = create_app()
|
|
12
|
+
|
|
13
|
+
Or run directly:
|
|
14
|
+
|
|
15
|
+
python -m prme.api
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from prme.api.app import create_app
|
|
19
|
+
|
|
20
|
+
__all__ = ["create_app"]
|
prme/api/__main__.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Entry point for ``python -m prme.api``.
|
|
2
|
+
|
|
3
|
+
Starts the PRME HTTP API server with default settings.
|
|
4
|
+
Configuration is loaded from environment variables (PRME_ prefix).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main() -> None:
|
|
13
|
+
"""Parse CLI arguments and start the server."""
|
|
14
|
+
parser = argparse.ArgumentParser(
|
|
15
|
+
description="PRME HTTP API Server",
|
|
16
|
+
prog="python -m prme.api",
|
|
17
|
+
# The unauthenticated override must be spelled out in full.
|
|
18
|
+
allow_abbrev=False,
|
|
19
|
+
)
|
|
20
|
+
parser.add_argument(
|
|
21
|
+
"--host",
|
|
22
|
+
default="127.0.0.1",
|
|
23
|
+
help=(
|
|
24
|
+
"Bind address (default: 127.0.0.1). A non-loopback address such "
|
|
25
|
+
"as 0.0.0.0 requires API credentials (PRME_API_USER_KEYS or "
|
|
26
|
+
"PRME_API_API_KEY); without them startup is refused. Only literal "
|
|
27
|
+
"loopback addresses and localhost count as loopback."
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"--port", type=int, default=8000, help="Port (default: 8000)"
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"--log-level", default="info", help="Log level (default: info)"
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--allow-unauthenticated-external-bind",
|
|
38
|
+
action="store_true",
|
|
39
|
+
help=(
|
|
40
|
+
"Start on a non-loopback --host with no API credentials. Only for "
|
|
41
|
+
"a server reachable solely through an authenticating reverse "
|
|
42
|
+
"proxy: the API itself accepts every request, and every caller "
|
|
43
|
+
"has operator access to all users' memories."
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
args = parser.parse_args()
|
|
47
|
+
|
|
48
|
+
from prme.api.server import UnauthenticatedBindError, run_server
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
run_server(
|
|
52
|
+
host=args.host,
|
|
53
|
+
port=args.port,
|
|
54
|
+
log_level=args.log_level,
|
|
55
|
+
allow_unauthenticated_external_bind=(
|
|
56
|
+
args.allow_unauthenticated_external_bind
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
except UnauthenticatedBindError as exc:
|
|
60
|
+
parser.error(str(exc))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
if __name__ == "__main__":
|
|
64
|
+
main()
|
prme/api/app.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""PRME FastAPI application factory.
|
|
2
|
+
|
|
3
|
+
Creates and configures the FastAPI app with lifespan management
|
|
4
|
+
for the MemoryEngine. The engine is stored in app.state and shared
|
|
5
|
+
across all request handlers.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from contextlib import asynccontextmanager
|
|
12
|
+
from typing import AsyncIterator
|
|
13
|
+
|
|
14
|
+
from fastapi import FastAPI, Request
|
|
15
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
16
|
+
from fastapi.responses import JSONResponse
|
|
17
|
+
|
|
18
|
+
from prme import __version__
|
|
19
|
+
from prme.config import PRMEConfig
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def create_app(config: PRMEConfig | None = None) -> FastAPI:
|
|
25
|
+
"""Create and configure the PRME FastAPI application.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
config: Optional PRME configuration. Defaults to PRMEConfig().
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Configured FastAPI application with engine lifespan management.
|
|
32
|
+
"""
|
|
33
|
+
if config is None:
|
|
34
|
+
config = PRMEConfig()
|
|
35
|
+
|
|
36
|
+
@asynccontextmanager
|
|
37
|
+
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
38
|
+
"""Manage MemoryEngine lifecycle."""
|
|
39
|
+
from prme.storage.engine import MemoryEngine
|
|
40
|
+
|
|
41
|
+
logger.info("Starting PRME MemoryEngine...")
|
|
42
|
+
engine = await MemoryEngine.create(config)
|
|
43
|
+
app.state.engine = engine
|
|
44
|
+
logger.info("PRME MemoryEngine ready (backend=%s)", config.backend)
|
|
45
|
+
|
|
46
|
+
yield
|
|
47
|
+
|
|
48
|
+
logger.info("Shutting down PRME MemoryEngine...")
|
|
49
|
+
await engine.close()
|
|
50
|
+
app.state.engine = None
|
|
51
|
+
logger.info("PRME MemoryEngine shut down")
|
|
52
|
+
|
|
53
|
+
app = FastAPI(
|
|
54
|
+
title="PRME API",
|
|
55
|
+
description="Portable Relational Memory Engine — HTTP API",
|
|
56
|
+
version=__version__,
|
|
57
|
+
lifespan=lifespan,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Expose config to request handlers (auth dependency reads it).
|
|
61
|
+
app.state.config = config
|
|
62
|
+
app.state.engine = None
|
|
63
|
+
|
|
64
|
+
# CORS — disabled unless origins are explicitly pinned (issue #34).
|
|
65
|
+
# Credentials are never allowed with a wildcard origin: Starlette
|
|
66
|
+
# reflects the request Origin in that combination, letting any
|
|
67
|
+
# website read responses cross-origin.
|
|
68
|
+
cors_origins = config.api.cors_origins
|
|
69
|
+
if cors_origins:
|
|
70
|
+
allow_credentials = (
|
|
71
|
+
config.api.cors_allow_credentials and "*" not in cors_origins
|
|
72
|
+
)
|
|
73
|
+
if config.api.cors_allow_credentials and not allow_credentials:
|
|
74
|
+
logger.warning(
|
|
75
|
+
"cors_allow_credentials ignored: wildcard origin in "
|
|
76
|
+
"cors_origins. Pin explicit origins to allow credentials."
|
|
77
|
+
)
|
|
78
|
+
app.add_middleware(
|
|
79
|
+
CORSMiddleware,
|
|
80
|
+
allow_origins=cors_origins,
|
|
81
|
+
allow_credentials=allow_credentials,
|
|
82
|
+
allow_methods=["*"],
|
|
83
|
+
allow_headers=["*"],
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Generic handler for unexpected errors: log details server-side,
|
|
87
|
+
# never echo internals to the caller (issue #34).
|
|
88
|
+
@app.exception_handler(Exception)
|
|
89
|
+
async def unhandled_exception_handler(
|
|
90
|
+
request: Request, exc: Exception
|
|
91
|
+
) -> JSONResponse:
|
|
92
|
+
logger.error(
|
|
93
|
+
"Unhandled error on %s %s", request.method, request.url.path,
|
|
94
|
+
exc_info=exc,
|
|
95
|
+
)
|
|
96
|
+
return JSONResponse(
|
|
97
|
+
status_code=500, content={"detail": "Internal server error"}
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Register routes
|
|
101
|
+
from prme.api.routes import public_router, router
|
|
102
|
+
|
|
103
|
+
app.include_router(public_router)
|
|
104
|
+
app.include_router(router)
|
|
105
|
+
|
|
106
|
+
return app
|