File size: 3,670 Bytes
db4d559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3786a3f
 
 
db4d559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0527a95
db4d559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import uuid
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.conf import settings

class User(AbstractUser):
    """
    Custom User Model to allow for seamless future attribute additions 
    without database schema breakage. Uses UUID as the primary key.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    def __str__(self):
        return self.username


class Document(models.Model):
    """
    Tracks uploaded documents, ingestion status, metadata, and error details.
    """
    class Status(models.TextChoices):
        PENDING = 'PENDING', 'Pending'
        PROCESSING = 'PROCESSING', 'Processing'
        COMPLETED = 'COMPLETED', 'Completed'
        FAILED = 'FAILED', 'Failed'

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, 
        on_delete=models.CASCADE, 
        related_name='documents'
    )
    name = models.CharField(max_length=255)
    file = models.FileField(upload_to='uploaded_documents/')
    status = models.CharField(
        max_length=20, 
        choices=Status.choices, 
        default=Status.PENDING
    )
    entity_count = models.IntegerField(default=0)
    relationship_count = models.IntegerField(default=0)
    error_message = models.TextField(blank=True, null=True)
    source = models.CharField(max_length=255, blank=True, default='', help_text="Optional source label (e.g. research-paper, internal-wiki)")
    processing_progress = models.IntegerField(default=0, help_text="Progress percentage (0-100)")
    processing_step = models.CharField(max_length=200, blank=True, default='', help_text="Current processing step description")
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.name} ({self.status})"


class QueryLog(models.Model):
    """
    Logs queries, selected retrieval strategies, generated answers, and response times.
    """
    class RetrievalMode(models.TextChoices):
        GRAPH = 'GRAPH', 'Graph Only'
        VECTOR = 'VECTOR', 'Vector Only'
        HYBRID = 'HYBRID', 'Hybrid'
        MULTIHOP = 'MULTIHOP', 'Multi-Hop'

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, 
        on_delete=models.CASCADE, 
        related_name='query_logs'
    )
    query_text = models.TextField()
    retrieval_mode = models.CharField(
        max_length=20, 
        choices=RetrievalMode.choices, 
        default=RetrievalMode.HYBRID
    )
    answer_text = models.TextField()
    response_time = models.FloatField(help_text="Response time in seconds")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"Query: {self.query_text[:30]}... ({self.retrieval_mode})"


class EvaluationPair(models.Model):
    """
    Stores target question-answer evaluation pairs to compute metrics against.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, 
        on_delete=models.CASCADE, 
        related_name='evaluation_pairs'
    )
    question = models.TextField()
    expected_answer = models.TextField()
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Question: {self.question[:40]}..."