Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions usaspending_api/llm/fixtures/ai_models.yaml
Comment thread
AHasan-FRB marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
- model: llm.aimodel
pk: 1
fields:
name: claude 4.5
model_id: anthropic.claude-sonnet-4-5-20250929-v1:0
provider: anthropic
- model: llm.aimodel
pk: 2
fields:
name: claude 3.7
model_id: anthropic.claude-3-7-sonnet-20250219-v1:0
provider: anthropic
- model: llm.aimodel
pk: 3
fields:
name: nova lite
model_id: amazon.nova-lite-v1:0
provider: amazon
- model: llm.aimodel
pk: 4
fields:
name: nova micro
model_id: amazon.nova-micro-v1:0
provider: amazon
11 changes: 11 additions & 0 deletions usaspending_api/llm/fixtures/prompts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- model: llm.prompts
pk: 1
fields:
description: initial system prompt for the search assistant
text: >
Comment thread
zachflanders-frb marked this conversation as resolved.
You are USAspending search assistant. You help the user search for federal spending.
- This is not a chat interface. You may not ask the user for clarification or additonal input after the initial query.
- You may need to call other tools before calling the `search_federal_contracts_and_assistance` tool in order to get valid input parameters to `search_federal_contracts_and_assistance`.
- You may only call the `search_federal_contracts_and_assistance` tool once. Calling `search_federal_contracts_and_assistance` terminates the conversation. Therefore, include all the relevant parameters in the first and only call to `search_federal_contracts_and_assistance`.
- Only include the relevant input paramaters to `search_federal_contracts_and_assistance`.
- You must call `search_federal_contracts_and_assistance`. Do not quit before calling this tool.
15 changes: 15 additions & 0 deletions usaspending_api/llm/management/load_llm_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.core.management.base import BaseCommand
from django.core.management import call_command


class Command(BaseCommand):
help = 'Load LLM fixture data for AI models and prompts'

def handle(self, *args, **options):
self.stdout.write('Loading AI models...')
call_command('loaddata', 'usaspending_api/llm/fixtures/ai_models.yaml')

self.stdout.write('Loading prompts...')
call_command('loaddata', 'usaspending_api/llm/fixtures/prompts.yaml')

self.stdout.write(self.style.SUCCESS('Successfully loaded LLM fixtures'))
107 changes: 107 additions & 0 deletions usaspending_api/llm/models/db_models.py
Comment thread
AHasan-FRB marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from django.db import models


class AIModel(models.Model):
name = models.CharField(max_length=100)
model_id = models.CharField(max_length=100)
provider = models.CharField(max_length=100)

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

class Meta:
db_table = "ai_model"
ordering = ["-id"]

class Prompts(models.Model):
Comment thread
AHasan-FRB marked this conversation as resolved.
description = models.TextField()
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
return self.description[:100]

class Meta:
db_table = "prompts"


class Session(models.Model):
ai_model = models.ForeignKey(AIModel, on_delete=models.SET_NULL, null=True, related_name="sessions")
tools = models.JSONField(default=list)
system_prompt = models.ForeignKey(Prompts, on_delete=models.SET_NULL, null=True, related_name="sessions")
started_at = models.DateTimeField(auto_now_add=True)
ended_at = models.DateTimeField(null=True, blank=True)
feedback = models.BooleanField(default=None, null=True, blank=True, help_text="positive=True, negative=False")
Comment thread
AHasan-FRB marked this conversation as resolved.

def __str__(self):
return f"Session {self.id} - {self.ai_model.name if self.ai_model else 'No Model'} ({self.started_at.strftime('%Y-%m-%d %H:%M')})"


class Meta:
db_table = "session"
ordering = ["-started_at"]
indexes = [
models.Index(fields=["-started_at"]),
models.Index(fields=["feedback"]),
]


class Message(models.Model):
session = models.ForeignKey(Session, on_delete=models.CASCADE, related_name="messages")
role = models.CharField(max_length=100)
message = models.TextField()
order = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
input_tokens = models.IntegerField(default=0)
output_tokens = models.IntegerField(default=0)
total_tokens = models.IntegerField(default=0)
Comment thread
AHasan-FRB marked this conversation as resolved.
Outdated
latency = models.IntegerField(default=0, help_text="latency in milliseconds")

def __str__(self):
preview = self.message[:50] + "..." if len(self.message) > 50 else self.message
return f"{self.role} (Order {self.order}): {preview}"

class Meta:
db_table = "message"
ordering = ["session", "order"]
indexes = [
models.Index(fields=["session", "order"]),
models.Index(fields=["created_at"]),
]
unique_together = [["session", "order"]]


class ToolUse(models.Model):
message = models.ForeignKey(Message, on_delete=models.CASCADE, related_name="tool_uses")
name = models.CharField(max_length=200)
tool_input = models.JSONField()
result = models.JSONField()
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
return f"{self.name} - {self.created_at.strftime('%Y-%m-%d %H:%M:%S')}"


class Meta:
db_table = "tool_use"
ordering = ["created_at"]
indexes = [
models.Index(fields=["name"]),
models.Index(fields=["created_at"]),
]

class LLMSearchQuery(models.Model):
user_query = models.TextField()
session = models.ForeignKey(Session, on_delete=models.CASCADE, related_name="search_queries")
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
preview = self.user_query[:75] + "..." if len(self.user_query) > 75 else self.user_query
return f"Query {self.id}: {preview}"


class Meta:
db_table = "llm_search_query"
indexes = [
models.Index(fields=["-created_at"]),
]
Comment thread
AHasan-FRB marked this conversation as resolved.
Outdated
Loading
Loading