Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding chat messages to the DB #121

Merged
merged 9 commits into from
Nov 4, 2024
Merged

Conversation

rijuma
Copy link
Member

@rijuma rijuma commented Oct 30, 2024

This update adds the last user message to the course chat view.

I've also added some constants to LearningAssistantMessage model for consistency.

Warning

I've added an extra validation on the endpoint requiring the last message from the chat to be from the user.

@rijuma rijuma force-pushed the rijuma/save-messages-to-db branch 4 times, most recently from 1f63bf7 to c98c8b2 Compare October 30, 2024 14:35
Copy link

github-actions bot commented Oct 30, 2024

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  learning_assistant
  api.py 201-202
  models.py
  serializers.py
  toggles.py 51
  views.py
  learning_assistant/migrations
  0008_alter_learningassistantmessage_role.py
Project Total  

This report was generated by python-coverage-comment-action

@rijuma rijuma force-pushed the rijuma/save-messages-to-db branch 4 times, most recently from 2e8ddd7 to 4f2529d Compare October 30, 2024 14:49
@rijuma rijuma marked this pull request as ready for review October 30, 2024 14:51
@rijuma rijuma changed the title feat: Adding chat messages to the DB (WIP) feat: Adding chat messages to the DB Oct 30, 2024
@@ -76,6 +79,15 @@ def post(self, request, course_run_id):
unit_id = request.query_params.get('unit_id')

message_list = request.data

# Check that the last message in the list corresponds to a user
new_user_message = message_list[-1]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand the code block and the comment. Can you explain more to help someone like to understand the logic better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the message_list array is empty?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assumed the endpoint was to process a new user message. Maybe I misunderstood it but if it is, then it should include at least one user message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to point out: We discussed this offline and came to the conclusion that the approach is correct.

Comment on lines +175 to +191
{'role': 'assistant', 'content': 'It is 4'},
{'role': 'user', 'content': 'And what else?'},
Copy link
Member Author

@rijuma rijuma Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a check that validates the last message from the list to be from a user.

course_id = CourseKeyField(max_length=255, db_index=True)
user = models.ForeignKey(USER_MODEL, db_index=True, on_delete=models.CASCADE)
role = models.CharField(max_length=64)
role = models.CharField(choices=Roles, max_length=64)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this doesn't affect the database, so no migration needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure? Did you run makemigrations?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't. I'm sorry for that.
Just added the migration file.

@@ -103,6 +115,22 @@ def post(self, request, course_run_id):
)
status_code, message = get_chat_response(prompt_template, message_list)

user = User.objects.get(id=request.user.id) # Based on the previous code, user exists.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel the code block below should be wrapped into a new function

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to the API module.

@@ -35,6 +38,27 @@ class CourseChatView(APIView):
authentication_classes = (SessionAuthentication, JwtAuthentication,)
permission_classes = (IsAuthenticated,)

def __save_user_interaction(self, user_id, user_message, assistant_message):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be moved to the api.py file? I also think it might make more sense for it to look like save_user_message(user_id, role, message), and call it twice from within the view.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to the API module and added two calls in the view.

@@ -103,6 +136,12 @@ def post(self, request, course_run_id):
)
status_code, message = get_chat_response(prompt_template, message_list)

self.__save_user_interaction(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be gated by a waffle flag, which also needs to be created.

Copy link
Member Author

@rijuma rijuma Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh shoot. I totally forgot about it. Thanks for calling this out!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added waffle flag and gated the functionality behind it.

@rijuma rijuma force-pushed the rijuma/save-messages-to-db branch 5 times, most recently from 84e2983 to e1c3471 Compare October 30, 2024 21:04
User = get_user_model()


class TestClient(Client):
class FakeClient(Client):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class was renamed to remove the following test warning:

tests/test_views.py:22
  /Users/(ueser)/edx/src/learning-assistant/tests/test_views.py:22: PytestCollectionWarning: cannot collect test class 'TestClient' because it has a __init__ constructor (from: tests/test_views.py)
    class TestClient(Client):

@rijuma rijuma force-pushed the rijuma/save-messages-to-db branch 2 times, most recently from 956d19d to e28918a Compare October 30, 2024 21:10
course_id = get_course_id(course_run_id)
user_id = request.user.id

if chat_history_enabled(course_id):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be the course_id or a course key?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. According to the code to check the flag we check for Learning Assistant enabled state is a CourseKey based on the course run. I'll update it quickly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@rijuma rijuma force-pushed the rijuma/save-messages-to-db branch 4 times, most recently from 9fa2e46 to 6106dc8 Compare October 31, 2024 17:27
Copy link
Member

@schenedx schenedx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

course_id = CourseKeyField(max_length=255, db_index=True)
user = models.ForeignKey(USER_MODEL, db_index=True, on_delete=models.CASCADE)
role = models.CharField(max_length=64)
role = models.CharField(choices=Roles, max_length=64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure? Did you run makemigrations?

@@ -189,6 +191,24 @@ def get_course_id(course_run_id):
return course_key


def save_chat_message(user_id, chat_role, message):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should also take in a course_id, and use that as a field in the message being saved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. I wonder why this wasn't detected on the unit tests, maybe there's a constraint missing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just updated save_chat_message() to take the Courserun Key and save it to the model.

@rijuma rijuma force-pushed the rijuma/save-messages-to-db branch 2 times, most recently from c20a920 to 2fe0ceb Compare November 4, 2024 18:29
@rijuma
Copy link
Member Author

rijuma commented Nov 4, 2024

Just to confirm, I've validated locally that no message is saved without enabling the feature flag and this is the result after enabling it:

+----+----------------------------+----------------------------+---------------------------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+
| id | created                    | modified                   | course_id                       | role      | content                                                                                                                                                              | user_id |
+----+----------------------------+----------------------------+---------------------------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+
|  1 | 2024-11-04 19:05:07.403363 | 2024-11-04 19:05:07.403363 | course-v1:edX+DemoX+Demo_Course | user      | marco                                                                                                                                                                |       3 |
|  2 | 2024-11-04 19:05:21.357636 | 2024-11-04 19:05:21.357636 | course-v1:edX+DemoX+Demo_Course | assistant | It seems like you might be looking for something specific. Could you please clarify your question or let me know how I can assist you with the Demonstration Course? |       3 |
+----+----------------------------+----------------------------+---------------------------------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+

@rijuma rijuma merged commit 758b657 into main Nov 4, 2024
4 checks passed
@rijuma rijuma deleted the rijuma/save-messages-to-db branch November 4, 2024 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants