Add Themis application with custom widgets, views, and utilities
- Implemented custom form widgets for date, time, and datetime fields with DaisyUI styling. - Created utility functions for formatting dates, times, and numbers according to user preferences. - Developed views for profile settings, API key management, and notifications, including health check endpoints. - Added URL configurations for Themis tests and main application routes. - Established test cases for custom widgets to ensure proper functionality and integration. - Defined project metadata and dependencies in pyproject.toml for package management.
This commit is contained in:
251
mnemosyne/library/models.py
Normal file
251
mnemosyne/library/models.py
Normal file
@@ -0,0 +1,251 @@
|
||||
"""
|
||||
Neo4j graph models for the Mnemosyne content library.
|
||||
|
||||
All content data (libraries, collections, items, chunks, concepts, images)
|
||||
lives in Neo4j as a knowledge graph. These models use neomodel's StructuredNode
|
||||
OGM — they do NOT participate in Django's ORM or migrations.
|
||||
"""
|
||||
|
||||
from neomodel import (
|
||||
ArrayProperty,
|
||||
DateTimeProperty,
|
||||
FloatProperty,
|
||||
IntegerProperty,
|
||||
JSONProperty,
|
||||
RelationshipTo,
|
||||
StringProperty,
|
||||
StructuredNode,
|
||||
StructuredRel,
|
||||
UniqueIdProperty,
|
||||
)
|
||||
|
||||
|
||||
# --- Relationship models ---
|
||||
|
||||
|
||||
class ReferencesRel(StructuredRel):
|
||||
"""Relationship properties for Item -> Concept REFERENCES edges."""
|
||||
|
||||
weight = FloatProperty(default=1.0)
|
||||
context = StringProperty(default="")
|
||||
|
||||
|
||||
class RelatedToRel(StructuredRel):
|
||||
"""Relationship properties for Item -> Item RELATED_TO edges."""
|
||||
|
||||
relationship_type = StringProperty(default="")
|
||||
weight = FloatProperty(default=1.0)
|
||||
|
||||
|
||||
class NearbyImageRel(StructuredRel):
|
||||
"""Relationship properties for Chunk -> Image HAS_NEARBY_IMAGE edges."""
|
||||
|
||||
proximity = StringProperty(default="same_page") # same_page, inline, same_slide, same_chapter
|
||||
|
||||
|
||||
# --- Node models ---
|
||||
|
||||
|
||||
class Library(StructuredNode):
|
||||
"""
|
||||
Top-level container representing a content library.
|
||||
|
||||
Each library has a type (fiction, technical, music, film, art, journal)
|
||||
that drives chunking strategy, embedding instructions, and LLM prompts.
|
||||
"""
|
||||
|
||||
uid = UniqueIdProperty()
|
||||
name = StringProperty(unique_index=True, required=True)
|
||||
library_type = StringProperty(
|
||||
required=True,
|
||||
choices={
|
||||
"fiction": "Fiction",
|
||||
"technical": "Technical",
|
||||
"music": "Music",
|
||||
"film": "Film",
|
||||
"art": "Art",
|
||||
"journal": "Journal",
|
||||
},
|
||||
)
|
||||
description = StringProperty(default="")
|
||||
|
||||
# Content-type configuration
|
||||
chunking_config = JSONProperty(default={})
|
||||
embedding_instruction = StringProperty(default="")
|
||||
reranker_instruction = StringProperty(default="")
|
||||
llm_context_prompt = StringProperty(default="")
|
||||
|
||||
created_at = DateTimeProperty(default_now=True)
|
||||
|
||||
# Relationships
|
||||
collections = RelationshipTo("Collection", "CONTAINS")
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} ({self.library_type})"
|
||||
|
||||
|
||||
class Collection(StructuredNode):
|
||||
"""
|
||||
A grouping of items within a library.
|
||||
|
||||
Examples: a book series, an album discography, a project folder.
|
||||
"""
|
||||
|
||||
uid = UniqueIdProperty()
|
||||
name = StringProperty(required=True)
|
||||
description = StringProperty(default="")
|
||||
metadata = JSONProperty(default={})
|
||||
|
||||
created_at = DateTimeProperty(default_now=True)
|
||||
|
||||
# Relationships
|
||||
items = RelationshipTo("Item", "CONTAINS")
|
||||
library = RelationshipTo("Library", "BELONGS_TO")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Item(StructuredNode):
|
||||
"""
|
||||
An individual piece of content: a document, song, image set, journal entry, etc.
|
||||
|
||||
Items store their original file in S3 (via s3_key) and are chunked
|
||||
for embedding and retrieval.
|
||||
"""
|
||||
|
||||
uid = UniqueIdProperty()
|
||||
title = StringProperty(required=True)
|
||||
item_type = StringProperty(default="")
|
||||
s3_key = StringProperty(default="")
|
||||
content_hash = StringProperty(index=True)
|
||||
file_type = StringProperty(default="")
|
||||
file_size = IntegerProperty(default=0)
|
||||
metadata = JSONProperty(default={})
|
||||
|
||||
created_at = DateTimeProperty(default_now=True)
|
||||
updated_at = DateTimeProperty(default_now=True)
|
||||
|
||||
# Embedding pipeline fields (Phase 2)
|
||||
embedding_status = StringProperty(
|
||||
default="pending",
|
||||
choices={
|
||||
"pending": "Pending",
|
||||
"processing": "Processing",
|
||||
"completed": "Completed",
|
||||
"failed": "Failed",
|
||||
},
|
||||
)
|
||||
embedding_model_name = StringProperty(default="")
|
||||
chunk_count = IntegerProperty(default=0)
|
||||
image_count = IntegerProperty(default=0)
|
||||
error_message = StringProperty(default="")
|
||||
|
||||
# Relationships
|
||||
chunks = RelationshipTo("Chunk", "HAS_CHUNK")
|
||||
images = RelationshipTo("Image", "HAS_IMAGE")
|
||||
concepts = RelationshipTo("Concept", "REFERENCES", model=ReferencesRel)
|
||||
related_items = RelationshipTo("Item", "RELATED_TO", model=RelatedToRel)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Chunk(StructuredNode):
|
||||
"""
|
||||
A text chunk extracted from an Item for embedding and retrieval.
|
||||
|
||||
Chunk text is stored in S3; text_preview holds the first 500 chars
|
||||
for Neo4j full-text indexing.
|
||||
"""
|
||||
|
||||
uid = UniqueIdProperty()
|
||||
chunk_index = IntegerProperty(required=True)
|
||||
chunk_s3_key = StringProperty(required=True)
|
||||
chunk_size = IntegerProperty(default=0)
|
||||
text_preview = StringProperty(default="") # First 500 chars for full-text index
|
||||
embedding = ArrayProperty(FloatProperty()) # 4096d vector
|
||||
|
||||
created_at = DateTimeProperty(default_now=True)
|
||||
|
||||
# Relationships
|
||||
mentions = RelationshipTo("Concept", "MENTIONS")
|
||||
nearby_images = RelationshipTo("Image", "HAS_NEARBY_IMAGE", model=NearbyImageRel)
|
||||
|
||||
def __str__(self):
|
||||
return f"Chunk {self.chunk_index} ({self.uid})"
|
||||
|
||||
|
||||
class Concept(StructuredNode):
|
||||
"""
|
||||
A named entity or topic extracted from content.
|
||||
|
||||
Concepts form the backbone of the knowledge graph, linking items
|
||||
and chunks through shared references.
|
||||
"""
|
||||
|
||||
uid = UniqueIdProperty()
|
||||
name = StringProperty(unique_index=True, required=True)
|
||||
concept_type = StringProperty(
|
||||
default="",
|
||||
choices={
|
||||
"person": "Person",
|
||||
"place": "Place",
|
||||
"topic": "Topic",
|
||||
"technique": "Technique",
|
||||
"theme": "Theme",
|
||||
},
|
||||
)
|
||||
embedding = ArrayProperty(FloatProperty()) # 4096d vector
|
||||
|
||||
# Relationships
|
||||
related_concepts = RelationshipTo("Concept", "RELATED_TO")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Image(StructuredNode):
|
||||
"""
|
||||
An image associated with an Item (cover art, diagram, photo, etc.).
|
||||
|
||||
The image file is stored in S3; embeddings enable multimodal search.
|
||||
"""
|
||||
|
||||
uid = UniqueIdProperty()
|
||||
s3_key = StringProperty(required=True)
|
||||
image_type = StringProperty(
|
||||
default="",
|
||||
choices={
|
||||
"cover": "Cover",
|
||||
"diagram": "Diagram",
|
||||
"artwork": "Artwork",
|
||||
"still": "Still",
|
||||
"photo": "Photo",
|
||||
},
|
||||
)
|
||||
description = StringProperty(default="")
|
||||
metadata = JSONProperty(default={})
|
||||
|
||||
created_at = DateTimeProperty(default_now=True)
|
||||
|
||||
# Relationships
|
||||
embeddings = RelationshipTo("ImageEmbedding", "HAS_EMBEDDING")
|
||||
|
||||
def __str__(self):
|
||||
return f"Image {self.image_type} ({self.uid})"
|
||||
|
||||
|
||||
class ImageEmbedding(StructuredNode):
|
||||
"""
|
||||
A multimodal embedding vector for an Image node.
|
||||
|
||||
Generated by Qwen3-VL for unified text+image vector space.
|
||||
"""
|
||||
|
||||
uid = UniqueIdProperty()
|
||||
embedding = ArrayProperty(FloatProperty()) # 4096d multimodal vector
|
||||
created_at = DateTimeProperty(default_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"ImageEmbedding ({self.uid})"
|
||||
Reference in New Issue
Block a user