-
Notifications
You must be signed in to change notification settings - Fork 53
AI-powered marking #1248
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
base: master
Are you sure you want to change the base?
AI-powered marking #1248
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this feature! Quite a bit of comments. Please look through, resolve them. I do have some clarification comments as well so please answer those as well.
One question I have is when are these comments used? I couldn't find anytime in which the comments are returned/retrieved to/by the FE.
@doc """ | ||
Gets an AI comment by ID. | ||
""" | ||
def get_ai_comment!(id), do: Repo.get!(AIComment, id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why we use get!
instead of get
Retrieves an AI comment for a specific submission and question. | ||
Returns `nil` if no comment exists. | ||
""" | ||
def get_ai_comments_for_submission(submission_id, question_id) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming implies you are getting all AI comments. Also what is the use case for getting only one of the comments?
""" | ||
def update_ai_comment(id, attrs) do | ||
id | ||
|> get_ai_comment!() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could raise an error which isn't handled (id not found in DB)
field(:submission_id, :integer) | ||
field(:question_id, :integer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these are FKs, you need to specify that in the schema
answer_query = | ||
if is_nil(question_id) do | ||
base_query | ||
else | ||
base_query |> where(question_id: ^question_id) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use case
instead
@openai_api_url "https://api.openai.com/v1/chat/completions" | ||
@model "gpt-4o" | ||
# To set whether LLM grading is enabled across Source Academy | ||
@default_llm_grading false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be done in the DBMS as mentioned above
|
||
alias Cadet.{Assessments, AIComments, Courses} | ||
|
||
@openai_api_url "https://api.openai.com/v1/chat/completions" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be in the confg file (env variable). @model
as well
answers_json: answers_json, | ||
response: response, | ||
error: error, | ||
inserted_at: NaiveDateTime.utc_now() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be automatically handled my Ecto
updated_attrs = Map.merge(Map.from_struct(existing_comment), attrs) | ||
|
||
case AIComments.update_ai_comment(existing_comment.id, updated_attrs) do | ||
{:ok, updated_comment} -> | ||
{:ok, updated_comment} | ||
|
||
{:error, changeset} -> | ||
Logger.error("Failed to update AI comment in database: #{inspect(changeset.errors)}") | ||
{:error, changeset} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably need to refactor this log_comment
function. It is doing more than just logging.
llm_prompt = | ||
answers | ||
|> List.first() | ||
|> Map.get(:question) | ||
|> Map.get(:question) | ||
|> Map.get("llm_prompt") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why we only use the first question's llm_prompt
? What about the other questions' prompts
Description
Created a new feature to automate feedback generation of code submissions in Source Academy, with the help of LLMs. This will help save TAs some time in grading code submissions from students!
generate_ai_comments
endpoint to fetch question details and generate AI-generated comments for submissions.save_chosen_comments
endpoint to save multiple chosen comments for a submission and question for logging purposes.save_final_comment
endpoint to save the final comment chosen for a submission for logging purposes.ai_comment_logs
table to log various data points from inputs, original student's code, outputs generated by LLM, comments chosen, and final comment.AIComments
module to handle creation, retrieval, and updates for AI comments, including saving final and chosen comments.AICodeAnalysisController
to handle AI comment generation, saving final comments, and saving chosen comments.generate_ai_comments
,save_final_comment
, andsave_chosen_comments
endpoints inAICodeAnalysisControllerTest
.Note: This may require changes to the DB diagram in README.md.
Type of Change
Checklist