tiennguyenbnbk commited on
Commit
fbe1bdb
1 Parent(s): abd1274

Upload 4 files

Browse files
Files changed (4) hide show
  1. app.py +121 -0
  2. chains.py +23 -0
  3. parsers.py +113 -0
  4. prompts.py +46 -0
app.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from textwrap import dedent
3
+
4
+ from chains import setup_chain_v2
5
+
6
+ chain = setup_chain_v2()
7
+
8
+ with gr.Blocks() as demo:
9
+ with gr.Row():
10
+ # --- Nhóm các thành phần nhập liệu ---
11
+ with gr.Column():
12
+ with gr.Group(): # Nhóm "Thái độ"
13
+ attitude_components = [
14
+ gr.Radio(["Con đi học đầy đủ", "Con chưa đi học đầy đủ"], label="Thái độ", show_label=True),
15
+ gr.Radio(["Con đi học đúng giờ", "Con vẫn còn đi học muộn"], show_label=False),
16
+ gr.Radio(["Con hoàn thành BTVN", "Con chưa hoàn thành đầy đủ BTVN"], show_label=False),
17
+ gr.Radio(["Con tập trung trong lớp học", "Con chưa tập trung trong lớp học"], show_label=False),
18
+ gr.Radio(["Con sôi nổi, hào hứng trong các buổi học", "Con cần được động viên, khích lệ thường xuyên"], show_label=False),
19
+ ]
20
+
21
+ with gr.Group(): # Nhóm "Kiến thức"
22
+ knowleadge_components = [
23
+ gr.Radio(["Con có vốn từ vựng phong phú", "Con có vốn từ vựng cơ bản", "Con cần trau dồi vốn từ vựng"], label="Kiến thức"),
24
+ gr.Textbox(lines=1, label="Con nhớ và sử dụng linh hoạt các từ vựng đã học trong chủ điểm:", show_label=True),
25
+ gr.Textbox(lines=1, label="Con chưa nhớ từ vựng trong chủ điểm:", show_label=True),
26
+ gr.Radio(["Con có thể sử dụng cấu trúc ngữ pháp thành thạo", "Con có thể sử dụng cấu trúc ngữ pháp cơ bản", "Con cần trau dồi cấu trúc ngữ pháp"], show_label=False),
27
+ gr.Textbox(lines=1, label="Các cấu trúc con đã thành thạo:", show_label=True),
28
+ gr.Textbox(lines=1, label="Các cấu trúc con chưa thành thạo:", show_label=True),
29
+ ]
30
+
31
+ with gr.Group(): # Nhóm "Tương tác"
32
+ interaction_components = [
33
+ gr.Radio(["Tích cực tham gia vào các hoạt động trên lớp", "Ít tham gia vào các hoạt động trên lớp"], label="Tương tác"),
34
+ gr.Radio(["Chăm chú nghe giảng", "Chưa chăm chú nghe giảng"], show_label=False),
35
+ gr.Radio(["Hăng hái giơ tay phát biểu và xây dựng bài", "Ít tương tác và chưa chủ động tham gia xây dựng bài"], show_label=False),
36
+ ]
37
+
38
+ with gr.Column(): # Nhóm "Kỹ năng"
39
+ skill_components = [
40
+ gr.Radio(["Con nghe hiểu và phản xạ tốt đối với các yêu cầu của thầy cô", "Con phản xạ còn chậm trước các yêu cầu của thầy cô"], label="Kỹ năng", info="", show_label=True),
41
+ gr.Radio(["Con thực hành thành thạo các dạng bài nghe", "Con cần rèn luyện thêm để cải thiện kỹ năng nghe với những dạng bài khác nhau"], label="", info="", show_label=False),
42
+ gr.Radio(["Con có giọng nói to, rõ ràng", "Giọng nói đôi khi nhỏ và không rõ ràng"], label="", info="", show_label=False),
43
+ gr.Radio(["Con phát âm đúng, đặc biệt là các âm cuối", "Con phát âm chưa hoàn toàn chính xác, đặc biệt là các âm cuối"], label="", info="", show_label=False),
44
+ gr.Radio(["Con có khả năng nói trôi chảy, lưu loát", "Con cần chú ý hơn về ngữ điệu khi nói, thỉnh thoảng con còn nói ngập ngừng, chưa thực sự lưu loát"], label="", info="", show_label=False),
45
+ gr.Radio(["Con đọc hiểu tốt và làm đúng yêu cầu đề bài", "Con cần luyện tập kỹ năng đọc để nắm vững toàn bộ yêu cầu đề bài"], label="", info="", show_label=False),
46
+ gr.Radio(["Con hiểu được nội dung chính và chi tiết quan trọng của bài đọc", "Con cần luyện tập thêm để hiểu được nội dung chính và chi tiết quan trọng trong bài đọc"], label="", info="", show_label=False),
47
+ gr.Radio(["Viết đúng chính tả", "Đôi khi viết sai chính tả"], label="", info="", show_label=False),
48
+ gr.Radio(["Viết đúng ngữ pháp và cấu trúc câu", "Khi viết còn mắc lỗi ngữ pháp và cấu trúc câu"], label="", info="", show_label=False),
49
+ gr.Radio(["Sử dụng từ vựng phong phú khi viết", "Từ vựng sử dụng chưa đa dạng"], label="", info="", show_label=False),
50
+ gr.Radio(["Khi viết con diễn đạt ý tưởng rõ ràng và mạch lạc", "Khi viết con diễn đạt ý tưởng chưa rõ ràng và mạch lạc"], label="", info="", show_label=False),
51
+ ]
52
+
53
+ # --- Nhóm các thành phần xuất kết quả ---
54
+ with gr.Column():
55
+ debug_output = gr.Textbox(label="Thông tin đánh giá", show_copy_button=True)
56
+ attitude_output = gr.Textbox(label="Thái độ", show_copy_button=True)
57
+ knowleadge_output = gr.Textbox(label="Kiến thức", show_copy_button=True)
58
+ skill_output = gr.Textbox(label="Kỹ năng", show_copy_button=True)
59
+ interaction_output = gr.Textbox(label="Tương tác", show_copy_button=True)
60
+ detail_output = gr.Textbox(label="Chi tiết", show_copy_button=True)
61
+
62
+ greet_btn = gr.Button("Tạo nhận xét")
63
+
64
+ # --- Hàm xử lý dữ liệu và tạo nhận xét ---
65
+ def gen(*args):
66
+ # Tách các tham số thành các nhóm tương ứng
67
+ attitude_data = args[:5]
68
+ knowleadge_data = args[5:11]
69
+ skill_data = args[11:22]
70
+ interaction_data = args[22:]
71
+
72
+ attitude_sentence = ""
73
+ for data in attitude_data:
74
+ if data:
75
+ attitude_sentence += data + ". "
76
+
77
+ knowleadge_sentence = ""
78
+ for idx, data in enumerate(knowleadge_data):
79
+ if data:
80
+ if idx == 1:
81
+ knowleadge_sentence += "Con nhớ và sử dụng linh hoạt các từ vựng đã học trong chủ điểm: " + data + ". "
82
+ elif idx == 2:
83
+ knowleadge_sentence += "Con chưa nhớ từ vựng trong chủ điểm: " + data + ". "
84
+ elif idx == 4:
85
+ knowleadge_sentence += "Các cấu trúc con đã thành thạo: " + data + ". "
86
+ elif idx == 5:
87
+ knowleadge_sentence += "Các cấu trúc con chưa thành thạo: " + data + ". "
88
+ else:
89
+ knowleadge_sentence += data + ". "
90
+
91
+ skill_sentence = ""
92
+ for data in skill_data:
93
+ if data:
94
+ skill_sentence += data + ". "
95
+
96
+ interaction_sentence = ""
97
+ for data in interaction_data:
98
+ if data:
99
+ interaction_sentence += data + ". "
100
+
101
+ full_sentence = dedent(f"""\
102
+ Thái độ: {attitude_sentence.strip() if len(attitude_sentence.strip()) else "Không có đánh giá"}
103
+ Kiến thức: {knowleadge_sentence.strip()if len(knowleadge_sentence.strip()) else "Không có đánh giá"}
104
+ Kỹ năng: {skill_sentence.strip()if len(skill_sentence.strip()) else "Không có đánh giá"}
105
+ Tương tác: {interaction_sentence.strip()if len(interaction_sentence.strip()) else "Không có đánh giá"}
106
+ """)
107
+ result = chain.invoke({"query": full_sentence})
108
+
109
+ return {
110
+ debug_output: full_sentence.strip(),
111
+ attitude_output: result['atitude'],
112
+ knowleadge_output: result['knowleadge'],
113
+ skill_output: result['skill'],
114
+ interaction_output: result['interaction'],
115
+ detail_output: result['detail']
116
+ }
117
+
118
+ greet_btn.click(gen, inputs=[*attitude_components, *knowleadge_components, *skill_components, *interaction_components], outputs=[debug_output, attitude_output, knowleadge_output, skill_output, interaction_output, detail_output])
119
+
120
+ if __name__ == "__main__":
121
+ demo.launch(server_name='192.168.8.76', server_port=7860,ssl_verify=False, auth=('admin', 'vuihoc.vn'))
chains.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_google_genai import GoogleGenerativeAI
2
+ from prompts import evaluation_prompt_v1, evaluation_prompt_v2
3
+ from parsers import evaluation_parser_v1, evaluation_parser_v2
4
+ from dotenv import load_dotenv
5
+ import os
6
+ load_dotenv()
7
+
8
+
9
+ def setup_chain_v1():
10
+ llm = GoogleGenerativeAI(model='gemini-1.5-pro',
11
+ temperature=0.5,
12
+ google_api_key=os.getenv('GOOGLE_API_KEY'))
13
+
14
+ chain = evaluation_prompt_v1 | llm | evaluation_parser_v1
15
+ return chain
16
+
17
+ def setup_chain_v2():
18
+ llm = GoogleGenerativeAI(model='gemini-1.5-pro',
19
+ temperature=0.5,
20
+ google_api_key=os.getenv('GOOGLE_API_KEY'))
21
+
22
+ chain = evaluation_prompt_v2 | llm | evaluation_parser_v2
23
+ return chain
parsers.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from json import JSONDecodeError
5
+ from typing import Any, List, Optional, Type, TypeVar, Union
6
+
7
+ import jsonpatch # type: ignore[import]
8
+ import pydantic # pydantic: ignore
9
+
10
+ from langchain_core.exceptions import OutputParserException
11
+ from langchain_core.output_parsers.format_instructions import JSON_FORMAT_INSTRUCTIONS
12
+ from langchain_core.output_parsers.transform import BaseCumulativeTransformOutputParser
13
+ from langchain_core.outputs import Generation
14
+ from langchain_core.utils.json import (
15
+ parse_and_check_json_markdown,
16
+ parse_json_markdown,
17
+ parse_partial_json,
18
+ )
19
+ from langchain_core.utils.pydantic import PYDANTIC_MAJOR_VERSION
20
+
21
+ from langchain_core.pydantic_v1 import BaseModel, Field
22
+
23
+ if PYDANTIC_MAJOR_VERSION < 2:
24
+ PydanticBaseModel = pydantic.BaseModel
25
+
26
+ else:
27
+ from pydantic.v1 import BaseModel # pydantic: ignore
28
+
29
+ # Union type needs to be last assignment to PydanticBaseModel to make mypy happy.
30
+ PydanticBaseModel = Union[BaseModel, pydantic.BaseModel] # type: ignore
31
+
32
+ TBaseModel = TypeVar("TBaseModel", bound=PydanticBaseModel)
33
+
34
+
35
+ class JsonOutputParser(BaseCumulativeTransformOutputParser[Any]):
36
+ """Parse the output of an LLM call to a JSON object.
37
+
38
+ When used in streaming mode, it will yield partial JSON objects containing
39
+ all the keys that have been returned so far.
40
+
41
+ In streaming, if `diff` is set to `True`, yields JSONPatch operations
42
+ describing the difference between the previous and the current object.
43
+ """
44
+
45
+ pydantic_object: Optional[Type[TBaseModel]] = None # type: ignore
46
+
47
+ def _diff(self, prev: Optional[Any], next: Any) -> Any:
48
+ return jsonpatch.make_patch(prev, next).patch
49
+
50
+ def _get_schema(self, pydantic_object: Type[TBaseModel]) -> dict[str, Any]:
51
+ if PYDANTIC_MAJOR_VERSION == 2:
52
+ if issubclass(pydantic_object, pydantic.BaseModel):
53
+ return pydantic_object.model_json_schema()
54
+ elif issubclass(pydantic_object, pydantic.v1.BaseModel):
55
+ return pydantic_object.schema()
56
+ return pydantic_object.schema()
57
+
58
+ def parse_result(self, result: List[Generation], *, partial: bool = False) -> Any:
59
+ text = result[0].text
60
+ text = text.strip()
61
+ if partial:
62
+ try:
63
+ return parse_json_markdown(text)
64
+ except JSONDecodeError:
65
+ return None
66
+ else:
67
+ try:
68
+ return parse_json_markdown(text)
69
+ except JSONDecodeError as e:
70
+ msg = f"Invalid json output: {text}"
71
+ raise OutputParserException(msg, llm_output=text) from e
72
+
73
+ def parse(self, text: str) -> Any:
74
+ return self.parse_result([Generation(text=text)])
75
+
76
+ def get_format_instructions(self) -> str:
77
+ if self.pydantic_object is None:
78
+ return "Return a JSON object."
79
+ else:
80
+ # Copy schema to avoid altering original Pydantic schema.
81
+ schema = {k: v for k, v in self._get_schema(self.pydantic_object).items()}
82
+
83
+ # Remove extraneous fields.
84
+ reduced_schema = schema
85
+ if "title" in reduced_schema:
86
+ del reduced_schema["title"]
87
+ if "type" in reduced_schema:
88
+ del reduced_schema["type"]
89
+ # Ensure json in context is well-formed with double quotes.
90
+ schema_str = json.dumps(reduced_schema, ensure_ascii=False)
91
+ return JSON_FORMAT_INSTRUCTIONS.format(schema=schema_str)
92
+
93
+ @property
94
+ def _type(self) -> str:
95
+ return "simple_json_output_parser"
96
+
97
+
98
+ class Evaluation(BaseModel):
99
+ """Nhận xét của giáo viên cho kết quả học tập của học sinh"""
100
+ summary: str = Field(description="Nhận xét ngắn gọn khoảng 50 từ")
101
+ detail: str = Field(description="Nhận xét chi tiết khoảng 200 từ")
102
+
103
+ evaluation_parser_v1 = JsonOutputParser(pydantic_object=Evaluation)
104
+
105
+ class EvaluationForStudent(BaseModel):
106
+ """Nhận xét của giáo viên cho kết quả học tập của học sinh"""
107
+ atitude: str = Field(description="Nhận xét ngắn gọn khoảng 50 từ cho thái độ của học sinh")
108
+ knowleadge: str = Field(description="Nhận xét ngắn gọn khoảng 50 từ cho kiến thức của học sinh")
109
+ skill: str = Field(description="Nhận xét ngắn gọn khoảng 50 từ cho kỹ năng của học sinh")
110
+ interaction: str = Field(description="Nhận xét ngắn gọn khoảng 50 từ cho tương tác của học sinh")
111
+ detail: str = Field(description="Nhận xét chi tiết khoảng 200 từ")
112
+
113
+ evaluation_parser_v2 = JsonOutputParser(pydantic_object=EvaluationForStudent)
prompts.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.prompts import PromptTemplate
2
+ from parsers import evaluation_parser_v1, evaluation_parser_v2
3
+
4
+ template_v1 = '''
5
+ Bạn là giáo viên của {student_name} trong suốt thời gian vừa qua tại Vui Học, hãy dựa trên những đánh giá rồi đưa ra nhận xét về kết quả học tập để gửi tới phụ huynh của học sinh {student_name}.
6
+ Hãy viết nhận xét với giọng điệu gần gũi, thân thiện, nhiều cảm xúc, xưng mình là cô gọi học sinh là con. Nhận xét của bạn sẽ giúp phụ huynh hiểu rõ hơn về tình hình học tập của học sinh.
7
+
8
+ Hãy viết nhận xét thành hai loại:
9
+ Nhận xét tóm tắt khoảng 50 từ về kết quả học tập, gọi học sinh là con thay vì tên riêng cho tóm tắt.
10
+ Nhận xét chi tiết khoảng 200 từ về kết quả học tập, hãy bắt đầu bằng lời chào phụ huynh học sinh và kết thúc bằng lời động viên.
11
+
12
+ Thông tin đánh giá:
13
+ {query}
14
+
15
+
16
+ {format_instructions}
17
+
18
+ '''
19
+
20
+ evaluation_prompt_v1 = PromptTemplate(
21
+ input_variables=["student_name", "query"],
22
+ template=template_v1,
23
+ partial_variables={"format_instructions": evaluation_parser_v1.get_format_instructions()},
24
+ )
25
+
26
+ template_v2 = '''
27
+ Bạn là giáo viên của học sinh trong suốt thời gian vừa qua tại Vui Học, hãy dựa trên những đánh giá rồi đưa ra nhận xét về kết quả học tập để gửi tới phụ huynh của học sinh.
28
+ Hãy viết nhận xét với giọng điệu gần gũi, thân thiện, nhiều cảm xúc tránh lặp từ, xưng mình là cô gọi học sinh là con thay vì tên riêng. Nhận xét của bạn sẽ giúp phụ huynh hiểu rõ hơn về tình hình học tập của học sinh.
29
+
30
+ Hãy viết nhận xét cho từng tiêu chí và tổng hợp chi tiết:
31
+ Nhận xét cho mỗi tiêu chí khoảng 50 từ, nếu không có thông tin đánh giá hãy bỏ qua tiêu chí đó.
32
+ Nhận xét chi tiết khoảng 200 từ về kết quả học tập, hãy bắt đầu bằng lời chào học sinh và kết thúc bằng lời động viên.
33
+
34
+ Thông tin đánh giá:
35
+ {query}
36
+
37
+
38
+ {format_instructions}
39
+
40
+ '''
41
+
42
+ evaluation_prompt_v2 = PromptTemplate(
43
+ input_variables=["student_name", "query"],
44
+ template=template_v2,
45
+ partial_variables={"format_instructions": evaluation_parser_v2.get_format_instructions()},
46
+ )