models.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import hashlib
  2. from django.db import models
  3. from django.core.validators import MinValueValidator, MaxValueValidator
  4. TEMPLATE_SYSTEM_PROMPT = """
  5. You are a helpful assistant designed to answer questions.
  6. Provide concise and accurate responses, ensuring you follow the provided instructions thoroughly.
  7. """.strip()
  8. TARGET_CHOICES = [
  9. ('test', 'test'),
  10. ('train', 'train'),
  11. ('dev', 'dev'),
  12. ('validation', 'validation'),
  13. ]
  14. ROLE_CHOICES = [
  15. ('assistant', 'assistant'),
  16. ('user', 'user'),
  17. ]
  18. CLIENT_CHOICES = [
  19. ('openai', 'OpenAI'),
  20. ('ollama', 'Ollama'),
  21. ('genai', 'Google GenAI'),
  22. ('anthropic', 'Anthropic'),
  23. ('togheter', 'Togheter.ai'),
  24. ('groq', 'Groq'),
  25. ]
  26. class Dataset(models.Model):
  27. class Meta:
  28. db_table = 'dataset'
  29. verbose_name = 'Dataset'
  30. verbose_name_plural = 'Datasets'
  31. name = models.CharField(max_length=100)
  32. description = models.TextField()
  33. created_at = models.DateTimeField(auto_now_add=True)
  34. updated_at = models.DateTimeField(auto_now=True)
  35. def __str__(self):
  36. return self.name
  37. class QA(models.Model):
  38. class Meta:
  39. db_table = 'qa'
  40. verbose_name = 'QA'
  41. verbose_name_plural = 'QAs'
  42. dataset = models.ForeignKey('Dataset', on_delete=models.CASCADE)
  43. question = models.TextField()
  44. category = models.CharField(max_length=256, null=True, blank=True, db_index=True)
  45. extra_info = models.JSONField(null=True, blank=True)
  46. correct_answer = models.TextField()
  47. target = models.CharField(
  48. max_length=100,
  49. default='test',
  50. choices=TARGET_CHOICES,
  51. db_index=True
  52. )
  53. options = models.JSONField(null=True, blank=True)
  54. xid = models.CharField(max_length=100, null=True, blank=True)
  55. context = models.TextField(null=True, blank=True)
  56. correct_answer_idx = models.CharField(max_length=100)
  57. hash = models.CharField(max_length=100, unique=True)
  58. def __str__(self):
  59. return self.question[:50] + (self.question[50:] and '...')
  60. def get_hash(self):
  61. txt = self.dataset.name + self.question
  62. if self.correct_answer:
  63. txt += self.correct_answer
  64. if self.correct_answer_idx:
  65. txt += self.correct_answer_idx
  66. if self.xid:
  67. txt += self.xid
  68. if self.target:
  69. txt += self.target
  70. if self.category:
  71. txt += self.category
  72. if self.extra_info:
  73. txt += ''.join(self.extra_info)
  74. if self.context:
  75. txt += self.context
  76. if self.options:
  77. txt += ''.join(self.options)
  78. if self.context:
  79. txt += self.context
  80. return hashlib.md5(txt.encode('utf-8')).hexdigest()
  81. def save(self, *args, **kwargs):
  82. self.hash = self.get_hash()
  83. super().save(*args, **kwargs)
  84. class LLMBackend(models.Model):
  85. class Meta:
  86. db_table = 'llm_backed'
  87. verbose_name = 'LLM Backend'
  88. verbose_name_plural = 'LLM Backends'
  89. name = models.CharField(max_length=100)
  90. client_type = models.CharField(
  91. max_length=100,
  92. default='openai',
  93. choices=CLIENT_CHOICES,
  94. db_index=True
  95. )
  96. parameters = models.JSONField(null=True, blank=True)
  97. def __str__(self):
  98. return self.name
  99. class LLMModel(models.Model):
  100. class Meta:
  101. db_table = 'llm_model'
  102. verbose_name = 'LLM Model'
  103. verbose_name_plural = 'LLM Models'
  104. name = models.CharField(max_length=100)
  105. backend = models.ForeignKey('LLMBackend', on_delete=models.CASCADE)
  106. parameters = models.JSONField(null=True, blank=True)
  107. created_at = models.DateTimeField(auto_now_add=True)
  108. updated_at = models.DateTimeField(auto_now=True)
  109. def __str__(self):
  110. return f"[{self.id}] {self.name}"
  111. class EvalConfig(models.Model):
  112. class Meta:
  113. db_table = 'eval_config'
  114. verbose_name = 'EvalConfig'
  115. verbose_name_plural = 'EvalConfig'
  116. name = models.CharField(max_length=100)
  117. description = models.TextField(null=True, blank=True)
  118. dataset = models.ForeignKey('Dataset', on_delete=models.CASCADE)
  119. sys_prompt = models.TextField(default=TEMPLATE_SYSTEM_PROMPT)
  120. final_answer_pattern = models.TextField(default='(?i)Final Answer\s*:\s*([A-E])')
  121. created_at = models.DateTimeField(auto_now_add=True)
  122. updated_at = models.DateTimeField(auto_now=True)
  123. def __str__(self):
  124. return self.name
  125. class RoleMessage(models.Model):
  126. class Meta:
  127. db_table = 'role_message'
  128. verbose_name = 'RoleMessage'
  129. verbose_name_plural = 'RoleMessage'
  130. role = models.CharField(max_length=100, choices=ROLE_CHOICES, db_index=True)
  131. content = models.TextField()
  132. eval_config = models.ForeignKey('EvalConfig', on_delete=models.CASCADE)
  133. def __str__(self):
  134. return self.content[:50] + (self.content[50:] and '...')
  135. class EvalSession(models.Model):
  136. class Meta:
  137. db_table = 'eval_session'
  138. verbose_name = 'EvalSession'
  139. verbose_name_plural = 'EvalSession'
  140. name = models.CharField(max_length=100)
  141. config = models.ForeignKey('EvalConfig', on_delete=models.CASCADE)
  142. llm_model = models.ForeignKey('LLMModel', on_delete=models.CASCADE)
  143. answer_interpreter = models.ForeignKey('AnswerInterpreter', on_delete=models.SET_NULL, null=True, blank=True)
  144. parameters = models.JSONField(null=True, blank=True)
  145. dataset_target = models.CharField(
  146. max_length=100,
  147. default='test',
  148. choices=TARGET_CHOICES,
  149. db_index=True
  150. )
  151. request_delay = models.IntegerField(
  152. null=True, blank=True,
  153. validators=[MinValueValidator(1), MaxValueValidator(600)],
  154. help_text="Request delay in seconds"
  155. )
  156. is_active = models.BooleanField(default=False)
  157. created_at = models.DateTimeField(auto_now_add=True)
  158. updated_at = models.DateTimeField(auto_now=True)
  159. def __str__(self):
  160. return f"{self.name} [{self.config.name} - {self.llm_model.name}]"
  161. def save(self, *args, **kwargs):
  162. if self.pk is None:
  163. self.parameters = self.llm_model.parameters
  164. super().save(*args, **kwargs)
  165. # accuracy property
  166. @property
  167. def accuracy(self):
  168. total_counts = self.evalanswer_set.count()
  169. if total_counts == 0:
  170. return 0
  171. return self.evalanswer_set.filter(is_correct=True).count() / self.evalanswer_set.count()
  172. class EvalAnswer(models.Model):
  173. class Meta:
  174. db_table = 'eval_answer'
  175. verbose_name = 'EvalAnswer'
  176. verbose_name_plural = 'EvalAnswer'
  177. eval_session = models.ForeignKey('EvalSession', on_delete=models.CASCADE)
  178. question = models.ForeignKey('QA', on_delete=models.CASCADE)
  179. instruction = models.TextField()
  180. assistant_answer = models.TextField()
  181. is_correct = models.BooleanField()
  182. created_at = models.DateTimeField(auto_now_add=True)
  183. hash = models.CharField(max_length=100)
  184. llm_backend = models.ForeignKey('LLMBackend', on_delete=models.CASCADE)
  185. llm_model = models.ForeignKey('LLMModel', on_delete=models.CASCADE)
  186. def __str__(self):
  187. return f"{self.question} - {self.is_correct}"
  188. class AnswerInterpreter(models.Model):
  189. class Meta:
  190. db_table = 'answer_interpreter'
  191. verbose_name = 'AnswerInterpreter'
  192. verbose_name_plural = 'AnswerInterpreter'
  193. name = models.CharField(max_length=100)
  194. prompt = models.TextField()
  195. llm_model = models.ForeignKey('LLMModel', on_delete=models.CASCADE)
  196. created_at = models.DateTimeField(auto_now_add=True)
  197. updated_at = models.DateTimeField(auto_now=True)
  198. def __str__(self):
  199. return self.name