theRealNG commited on
Commit
d9efaab
·
1 Parent(s): b36893b

tests(suggest_expectations): write test cases

Browse files
app/tests/suggest_expectations_test.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_openai import ChatOpenAI
2
+ from app.workflows.courses.suggest_expectations import SuggestExpectations
3
+ from langsmith.evaluation import LangChainStringEvaluator, evaluate
4
+ from langsmith.schemas import Example, Run
5
+ from typing import Any, Optional, TypedDict
6
+
7
+ database_name = "course-learn-suggest-expectations"
8
+ evaluator_llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
9
+
10
+
11
+ class SingleEvaluatorInput(TypedDict):
12
+ """The input to a `StringEvaluator`."""
13
+
14
+ prediction: str
15
+ """The prediction string."""
16
+ reference: Optional[Any]
17
+ """The reference string."""
18
+ input: Optional[str]
19
+ """The input string."""
20
+
21
+
22
+ def generate_expectations(example: dict):
23
+ chain = SuggestExpectations()._build_chain()
24
+ response = chain.invoke({
25
+ "course": example["course"], "module": example["module"], "tasks": example["tasks"],
26
+ "format_instructions": example["format_instructions"],
27
+ "existing_expectations": example["existing_expectations"]
28
+ })
29
+ return response
30
+
31
+
32
+ def similarity_search(org_str, test_strs):
33
+ most_similar = None
34
+ min_similarity = float('inf')
35
+
36
+ similarity_qa_evaluator = LangChainStringEvaluator(
37
+ "embedding_distance",
38
+ config={"distance_metric": "cosine"},
39
+ )
40
+
41
+ for test_itr in test_strs:
42
+ eval_inputs = SingleEvaluatorInput(
43
+ prediction=org_str,
44
+ reference=test_itr
45
+ )
46
+
47
+ result = similarity_qa_evaluator.evaluator.evaluate_strings(
48
+ **eval_inputs)
49
+ similarity_distance = result['score']
50
+
51
+ if abs(similarity_distance) < min_similarity:
52
+ similarity = 1 - similarity_distance
53
+ result['score'] = similarity
54
+ most_similar = {"key": "similarity", **result,
55
+ "prediction": test_itr,
56
+ "reference": org_str}
57
+ min_similarity = abs(similarity_distance)
58
+
59
+ if most_similar:
60
+ return most_similar
61
+
62
+
63
+ def custom_evaluator(root_run: Run, example: Example) -> dict:
64
+ results = []
65
+ for output_expectation_obj in root_run.outputs['expectations']:
66
+ output_expectation = output_expectation_obj['expectation']
67
+ most_similar = similarity_search(
68
+ output_expectation,
69
+ [item["expectation"] for item in example.outputs["expectations"]]
70
+ )
71
+ results.append(most_similar)
72
+
73
+ return {"results": results}
74
+
75
+
76
+ def build_evaluators():
77
+ response = evaluate(
78
+ generate_expectations,
79
+ data=database_name,
80
+ evaluators=[custom_evaluator],
81
+ experiment_prefix="alpha",
82
+ )
83
+
84
+ build_evaluators()
app/workflows/courses/__init__.py ADDED
File without changes
app/workflows/courses/suggest_check_question.py CHANGED
@@ -19,6 +19,7 @@ class Response(BaseModel):
19
  expectation: str
20
  check_question: str
21
 
 
22
  class CheckQuestion(BaseModel):
23
  check_question: str = Field(
24
  description="Targeted question that the course designer have developed to assess the learner's understanding of the learning outcomes.")
@@ -38,6 +39,20 @@ class SuggestCheckQuestion:
38
  }
39
 
40
  def _get_check_quesiton(self):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  parser = JsonOutputParser(pydantic_object=CheckQuestion)
42
  prompt = hub.pull("course_learn_suggest_check_question")
43
  llm = ChatOpenAI(model=os.environ['OPENAI_MODEL'], temperature=0.2)
@@ -51,12 +66,4 @@ class SuggestCheckQuestion:
51
  }
52
  })
53
 
54
- with callbacks.collect_runs() as cb:
55
- llm_response = chain.invoke({
56
- "course": self.course, "module": self.module, "tasks": "* " + ("\n* ".join(self.tasks)),
57
- "format_instructions": parser.get_format_instructions(),
58
- "learning_outcome": self.learning_outcome
59
- })
60
- self.run_id = cb.traced_runs[0].id
61
-
62
- return llm_response
 
19
  expectation: str
20
  check_question: str
21
 
22
+
23
  class CheckQuestion(BaseModel):
24
  check_question: str = Field(
25
  description="Targeted question that the course designer have developed to assess the learner's understanding of the learning outcomes.")
 
39
  }
40
 
41
  def _get_check_quesiton(self):
42
+ parser = JsonOutputParser(pydantic_object=CheckQuestion)
43
+ chain = self._build_chain()
44
+
45
+ with callbacks.collect_runs() as cb:
46
+ llm_response = chain.invoke({
47
+ "course": self.course, "module": self.module, "tasks": "* " + ("\n* ".join(self.tasks)),
48
+ "format_instructions": parser.get_format_instructions(),
49
+ "learning_outcome": self.learning_outcome
50
+ })
51
+ self.run_id = cb.traced_runs[0].id
52
+
53
+ return llm_response
54
+
55
+ def _build_chain(self):
56
  parser = JsonOutputParser(pydantic_object=CheckQuestion)
57
  prompt = hub.pull("course_learn_suggest_check_question")
58
  llm = ChatOpenAI(model=os.environ['OPENAI_MODEL'], temperature=0.2)
 
66
  }
67
  })
68
 
69
+ return chain
 
 
 
 
 
 
 
 
app/workflows/courses/suggest_expectations.py CHANGED
@@ -45,17 +45,7 @@ class SuggestExpectations:
45
 
46
  def _get_suggestions(self):
47
  parser = JsonOutputParser(pydantic_object=Expectations)
48
- prompt = hub.pull("course_learn_suggest_expectations_from_learner")
49
- llm = ChatOpenAI(model=os.environ['OPENAI_MODEL'], temperature=0.2)
50
- chain = (prompt | llm | parser).with_config({
51
- "tags": ["course_learn", "suggest_expectations"], "run_name": "Suggest Module Expectations",
52
- "metadata": {
53
- "versoin": "v1.0.0",
54
- "growth_activity": "course_learn",
55
- "env": os.environ["ENV"],
56
- "model": os.environ["OPENAI_MODEL"],
57
- }
58
- })
59
 
60
  # Existing Expectations
61
  existing_expectations = []
@@ -81,6 +71,22 @@ class SuggestExpectations:
81
 
82
  return llm_response
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
  # Example usage
86
  # suggester = SuggestExpectations()
 
45
 
46
  def _get_suggestions(self):
47
  parser = JsonOutputParser(pydantic_object=Expectations)
48
+ chain = self._build_chain()
 
 
 
 
 
 
 
 
 
 
49
 
50
  # Existing Expectations
51
  existing_expectations = []
 
71
 
72
  return llm_response
73
 
74
+ def _build_chain(self):
75
+ parser = JsonOutputParser(pydantic_object=Expectations)
76
+ prompt = hub.pull("course_learn_suggest_expectations_from_learner")
77
+ llm = ChatOpenAI(model=os.environ['OPENAI_MODEL'], temperature=0.2)
78
+ chain = (prompt | llm | parser).with_config({
79
+ "tags": ["course_learn", "suggest_expectations"], "run_name": "Suggest Module Expectations",
80
+ "metadata": {
81
+ "versoin": "v1.0.0",
82
+ "growth_activity": "course_learn",
83
+ "env": os.environ["ENV"],
84
+ "model": os.environ["OPENAI_MODEL"],
85
+ }
86
+ })
87
+
88
+ return chain
89
+
90
 
91
  # Example usage
92
  # suggester = SuggestExpectations()