defmodule Medicode.CodingTest do use Medicode.DataCase import Medicode.TranscriptionChunksFixtures alias Medicode.Coding alias Medicode.Coding.CodeVector alias Medicode.Feedback.CodeFeedback def create_code_vector!(code, description) do description_vector = Coding.compute_vector_as_list(description) changeset = CodeVector.changeset(%CodeVector{}, %{ code: code, description: description, description_vector: description_vector }) Repo.insert!(changeset) end def create_code_feedback!(text, response, for_code) do code_vector = Repo.one(from v in CodeVector, where: v.code == ^for_code) text_vector = Coding.compute_vector_as_list(text) changeset = CodeFeedback.changeset(%CodeFeedback{}, %{ text: text, text_vector: text_vector, response: response, code_vector_id: code_vector.id }) Repo.insert!(changeset) end describe "process_chunk/2" do @input_text "This 55-year-old man with known coronary artery disease comes for a follow-up visit today." @feedback_text "A 42-year-old man arrived for a return check-up who had a past history of coronary artery disease." setup do create_code_vector!("74685", "Coronary artery anomaly") create_code_vector!("41412", "Dissection of coronary artery") create_code_vector!("V717", "Observation for suspected cardiovascular disease") create_code_vector!("V812", "Screening for other and unspecified cardiovascular conditions") create_code_vector!("V4589", "Other postprocedural status") input_chunk = transcription_chunk_fixture(%{text: @input_text}) feedback_chunk = transcription_chunk_fixture(%{text: @feedback_text}) {:ok, input_chunk: input_chunk, feedback_chunk: feedback_chunk} end test "Codes can be weighted multiple times when multiple prior feedback items exist for a single code", %{input_chunk: chunk} do # One negative feedback item moves the code from 1st to 4th (x0.9). # The net result of 2 negative and 1 positive (x0.891) is to remove the code from the results. create_code_feedback!(@feedback_text, false, "74685") create_code_feedback!(@feedback_text, true, "74685") create_code_feedback!(@feedback_text, false, "74685") results = Coding.process_chunk(chunk) assert Enum.map(results, & &1.code) == ["41412", "V717", "V812"] assert Enum.all?(results, &(&1.weighting == [:none])) end test "Weighting can cause codes to appear in results that wouldn't have been included from the initial similarity query", %{input_chunk: chunk} do # E.g. weighting up a code that isn't in the initial results create_code_feedback!(@feedback_text, true, "V4589") results = Coding.process_chunk(chunk) assert Enum.map(results, & &1.code) == ["74685", "41412", "V717", "V812", "V4589"] assert Enum.map(results, & &1.weighting) == [ [:none], [:none], [:none], [:none], [:positive] ] end test "Codes are unweighted when no prior feedback", %{input_chunk: chunk} do results = Coding.process_chunk(chunk) assert Enum.map(results, & &1.code) == ["74685", "41412", "V717", "V812"] assert Enum.all?(results, &(&1.weighting == [:none])) end test "Code is ranked higher when prior positive feedback", %{input_chunk: chunk} do create_code_feedback!(@feedback_text, true, "V717") results = Coding.process_chunk(chunk) assert Enum.map(results, & &1.code) == ["V717", "74685", "41412", "V812"] assert Enum.map(results, & &1.weighting) == [[:positive], [:none], [:none], [:none]] end test "Code is ranked lower when prior negative feedback", %{input_chunk: chunk} do create_code_feedback!(@feedback_text, false, "74685") results = Coding.process_chunk(chunk) assert Enum.map(results, & &1.code) == ["41412", "V717", "V812", "74685"] assert Enum.map(results, & &1.weighting) == [[:none], [:none], [:none], [:negative]] end test "Code with low similarity score is removed from result when prior negative feedback", %{ input_chunk: chunk } do create_code_feedback!(@feedback_text, false, "V717") results = Coding.process_chunk(chunk) assert Enum.map(results, & &1.code) == ["74685", "41412", "V812"] assert Enum.map(results, & &1.weighting) == [[:none], [:none], [:none]] end end end