Skip to content

Commit

Permalink
Threads per assistant (optional)
Browse files Browse the repository at this point in the history
  • Loading branch information
fjsj committed Oct 3, 2024
1 parent 1d6377e commit 87b19f2
Show file tree
Hide file tree
Showing 18 changed files with 253 additions and 86 deletions.
19 changes: 17 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ If you encounter an error regarding the Python version required for the project,
pyenv install
```


#### Frontend

Go to the frontend directory and install the Node dependencies:
Expand All @@ -60,6 +59,15 @@ pre-commit install

It's critical to run the pre-commit hooks before pushing your code to follow the project's code style, and avoid linting errors.

### Updating the OpenAPI schema

It's critical to update the OpenAPI schema when you make changes to the `django_ai_assistant/api/views.py` or related files:

```bash
poetry run python manage.py generate_openapi_schema --output frontend/openapi_schema.json
sh -c 'cd frontend && pnpm run generate-client'
```

### Developing with the example project

Run the frontend project in `build:watch` mode:
Expand Down Expand Up @@ -105,6 +113,13 @@ Then, you will run the tests in record mode:
poetry run pytest --record-mode=once
```

To run frontend tests:

```bash
cd frontend
pnpm run test
```

## Documentation

We use [mkdocs-material](https://squidfunk.github.io/mkdocs-material/) to generate the documentation from markdown files.
Expand All @@ -123,7 +138,7 @@ poetry run mkdocs serve

To release and publish a new version, follow these steps:

1. Update the version in `pyproject.toml` and `frontend/package.json`.
1. Update the version in `pyproject.toml`, `frontend/package.json` and `example/package.json`.
2. Re-install the local version of the Python project: `poetry install`
3. In the project root, run `poetry run python manage.py generate_openapi_schema --output frontend/openapi_schema.json` to update the OpenAPI schema.
4. Re-install the local version of the frontend project:
Expand Down
2 changes: 2 additions & 0 deletions django_ai_assistant/api/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ class Meta:
fields = (
"id",
"name",
"assistant_id",
"created_at",
"updated_at",
)


class ThreadIn(Schema):
name: str = Field(default_factory=lambda: timezone.now().strftime("%Y-%m-%d %H:%M"))
assistant_id: str | None = None


class ThreadMessageIn(Schema):
Expand Down
9 changes: 6 additions & 3 deletions django_ai_assistant/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,17 @@ def get_assistant(request, assistant_id: str):


@api.get("threads/", response=List[Thread], url_name="threads_list_create")
def list_threads(request):
return list(use_cases.get_threads(user=request.user))
def list_threads(request, assistant_id: str | None = None):
return list(use_cases.get_threads(user=request.user, assistant_id=assistant_id))


@api.post("threads/", response=Thread, url_name="threads_list_create")
def create_thread(request, payload: ThreadIn):
name = payload.name
return use_cases.create_thread(name=name, user=request.user, request=request)
assistant_id = payload.assistant_id
return use_cases.create_thread(
name=name, assistant_id=assistant_id, user=request.user, request=request
)


@api.get("threads/{thread_id}/", response=Thread, url_name="thread_detail_update_delete")
Expand Down
35 changes: 30 additions & 5 deletions django_ai_assistant/helpers/use_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,16 @@ def create_message(
def create_thread(
name: str,
user: Any,
assistant_id: str | None = None,
request: HttpRequest | None = None,
) -> Thread:
"""Create a thread.\n
Uses `AI_ASSISTANT_CAN_CREATE_THREAD_FN` permission to check if user can create a thread.
Args:
name (str): Thread name
assistant_id (str | None): Assistant ID to associate the thread with.
If empty or None, the thread is not associated with any assistant.
user (Any): Current user
request (HttpRequest | None): Current request, if any
Returns:
Expand All @@ -159,7 +162,7 @@ def create_thread(
if not can_create_thread(user=user, request=request):
raise AIUserNotAllowedError("User is not allowed to create threads")

thread = Thread.objects.create(name=name, created_by=user)
thread = Thread.objects.create(name=name, created_by=user, assistant_id=assistant_id or "")
return thread


Expand Down Expand Up @@ -188,15 +191,37 @@ def get_single_thread(
return thread


def get_threads(user: Any) -> list[Thread]:
"""Get all user owned threads.\n
def get_threads(
user: Any,
assistant_id: str | None = None,
request: HttpRequest | None = None,
) -> list[Thread]:
"""Get all threads for the user.\n
Uses `AI_ASSISTANT_CAN_VIEW_THREAD_FN` permission to check the threads the user can see,
and returns only the ones the user can see.
Args:
user (Any): Current user
assistant_id (str | None): Assistant ID to filter threads by.
If empty or None, all threads for the user are returned.
request (HttpRequest | None): Current request, if any
Returns:
list[Thread]: List of thread model instances
list[Thread]: QuerySet of Thread model instances
"""
return list(Thread.objects.filter(created_by=user))
threads = Thread.objects.filter(created_by=user)

if assistant_id:
threads = threads.filter(assistant_id=assistant_id)

return list(
threads.filter(
id__in=[
thread.id
for thread in threads
if can_view_thread(thread=thread, user=user, request=request)
]
)
)


def update_thread(
Expand Down
18 changes: 18 additions & 0 deletions django_ai_assistant/migrations/0006_thread_assistant_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.1.1 on 2024-10-03 13:22

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('django_ai_assistant', '0005_alter_message_options'),
]

operations = [
migrations.AddField(
model_name='thread',
name='assistant_id',
field=models.CharField(blank=True, max_length=255),
),
]
2 changes: 2 additions & 0 deletions django_ai_assistant/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class Thread(models.Model):
null=True,
)
"""User who created the thread. Can be null. Set to null/None when user is deleted."""
assistant_id = models.CharField(max_length=255, blank=True)
"""Associated assistant ID. Can be empty."""
created_at = models.DateTimeField(auto_now_add=True)
"""Date and time when the thread was created.
Automatically set when the thread is created."""
Expand Down
2 changes: 1 addition & 1 deletion example/assets/js/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export function Chat({ assistantId }: { assistantId: string }) {
const [activeThread, setActiveThread] = useState<Thread | null>(null);
const [inputValue, setInputValue] = useState<string>("");

const { fetchThreads, threads, createThread, deleteThread } = useThreadList();
const { fetchThreads, threads, createThread, deleteThread } = useThreadList({ assistantId });
const {
fetchMessages,
messages,
Expand Down
1 change: 0 additions & 1 deletion example/demo/templates/demo/chat_thread.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
{% if message.type == "ai" %}AI{% else %}User{% endif %}
</strong>
</span>

<span>{{ message.content|markdown }}</span>
</div>
{% endfor %}
Expand Down
1 change: 0 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"@mantine/notifications": "^7.11.0",
"@tabler/icons-react": "^3.7.0",
"cookie": "^0.6.0",
"django-ai-assistant-client": "0.0.1",
"modern-normalize": "^2.0.0",
"react-markdown": "^9.0.1",
"react-router-dom": "^6.24.0"
Expand Down
64 changes: 0 additions & 64 deletions example/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 87b19f2

Please sign in to comment.