Dinh Thieu Quang commited on
Commit
3298301
2 Parent(s): 94b61d7 a37b78a

Merge pull request #29 from fsa-simpleqt/phase3/quangdt

Browse files
app/modules/__init__.py CHANGED
@@ -6,6 +6,7 @@ from app.modules.matching_cv import cvmatching_router
6
  from app.modules.crud_question_test import crud_question_tests_router
7
  from app.modules.crud_cvs import crud_cvs_router
8
  from app.modules.crud_jds import crud_jds_router
 
9
 
10
  modules_router = APIRouter(prefix="/modules", tags=["modules"])
11
  modules_router.include_router(qtretrieval_router)
@@ -13,6 +14,7 @@ modules_router.include_router(cvmatching_router)
13
  modules_router.include_router(crud_question_tests_router)
14
  modules_router.include_router(crud_cvs_router)
15
  modules_router.include_router(crud_jds_router)
 
16
 
17
  @modules_router.get("/")
18
  async def index():
 
6
  from app.modules.crud_question_test import crud_question_tests_router
7
  from app.modules.crud_cvs import crud_cvs_router
8
  from app.modules.crud_jds import crud_jds_router
9
+ from app.modules.question_rag import quiz_gen_router
10
 
11
  modules_router = APIRouter(prefix="/modules", tags=["modules"])
12
  modules_router.include_router(qtretrieval_router)
 
14
  modules_router.include_router(crud_question_tests_router)
15
  modules_router.include_router(crud_cvs_router)
16
  modules_router.include_router(crud_jds_router)
17
+ modules_router.include_router(quiz_gen_router)
18
 
19
  @modules_router.get("/")
20
  async def index():
app/modules/question_rag/__init__.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, UploadFile, File
2
+ from typing import Annotated
3
+
4
+ from app.modules.question_rag.models.question_rag_logic import question_rag
5
+ from app.modules.question_tests_retrieval.models.jd2text import jobdes2text
6
+
7
+ quiz_gen_router = APIRouter(prefix="/quiz_gen", tags=["quiz_gen"])
8
+
9
+ @quiz_gen_router.get("/")
10
+ async def index():
11
+ return {"message": "Welcome to quiz generator page"}
12
+
13
+ @quiz_gen_router.post("/quiz_gen")
14
+ # only upload .txt file
15
+ async def quiz_gen(txt_file: Annotated[UploadFile, File(..., description="The JD file (only .txt file)", media_type=["text/plain"])]):
16
+ try:
17
+ # read the txt file with format
18
+ jobdes = txt_file.file.read().decode("utf-8")
19
+ sumaryjd_text = jobdes2text(jobdes)
20
+ if question_rag(sumaryjd_text):
21
+ return {"message": "Generate quiz success",
22
+ "quiz": question_rag(sumaryjd_text)}
23
+ else:
24
+ return {"message": "Please upload only .txt file", "error": str(e)}
25
+ except Exception as e:
26
+ return {"message": "Please upload only .txt file", "error": str(e)}
app/modules/question_rag/models/question_rag_logic.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_google_genai import ChatGoogleGenerativeAI
2
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings
3
+ from langchain_core.prompts import ChatPromptTemplate
4
+ from langchain.chains.combine_documents import create_stuff_documents_chain
5
+ from langchain.chains import create_retrieval_chain
6
+ from langchain_core.output_parsers import JsonOutputParser
7
+
8
+ from langchain_community.vectorstores import Qdrant
9
+ import qdrant_client
10
+
11
+ import os
12
+ from dotenv import load_dotenv
13
+
14
+ # load the environment variables
15
+ load_dotenv()
16
+
17
+ # Define the google api key
18
+ os.environ['GOOGLE_API_KEY'] = os.getenv('GOOGLE_API_KEY')
19
+ os.environ['QDRANT_API_KEY'] = os.getenv('QDRANT_API_KEY')
20
+ os.environ['QDRANT_URL'] = os.getenv('QDRANT_URL')
21
+
22
+ GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
23
+ QDRANT_API_KEY = os.environ.get("QDRANT_API_KEY")
24
+ QDRANT_URL = os.environ.get("QDRANT_URL")
25
+
26
+ def question_rag(jobtext: str):
27
+ llm = ChatGoogleGenerativeAI(model="gemini-pro", google_api_key=GOOGLE_API_KEY, request_timeout=120)
28
+
29
+ embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
30
+
31
+ client = qdrant_client.QdrantClient(
32
+ url=QDRANT_URL,
33
+ api_key=QDRANT_API_KEY,
34
+ )
35
+
36
+ doc_store = Qdrant(
37
+ client=client,
38
+ collection_name="rag_documents_test",
39
+ embeddings=embeddings,
40
+ )
41
+
42
+ json_parser = JsonOutputParser()
43
+
44
+ prompt = ChatPromptTemplate.from_template("""
45
+ Answer the question based only on the following context:
46
+ <context>
47
+ {context}
48
+ </context>
49
+
50
+ Generate a 10 quiz suitable for the given job description "{input}". Do not include "All of the above" answers.
51
+ Output format is JSON:
52
+ ("__count__": 10, "data": ( "id": "", "question": "", "choices": [ "A. ", "B. ", "C.", "D. " ], "explanation": "", "answer": "", "level": "", "domain": "" )).
53
+ About level help me three levels: "Fresher, Junior, Senior".
54
+ """)
55
+
56
+ document_chain = create_stuff_documents_chain(llm, prompt, output_parser=json_parser)
57
+
58
+ retriever = doc_store.as_retriever()
59
+ retrieval_chain = create_retrieval_chain(retriever, document_chain)
60
+ response = retrieval_chain.invoke({"input": jobtext})
61
+
62
+ return response["answer"]
app/modules/question_tests_retrieval/models/jd2text.py CHANGED
@@ -15,7 +15,7 @@ GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
15
  # define the parser object
16
  parser = JsonOutputParser()
17
 
18
- def jobdes2text(jobdes):
19
  # setup the gemini pro
20
  llm = ChatGoogleGenerativeAI(model="gemini-pro", temperature=0.3, convert_system_message_to_human=True, api_key=GOOGLE_API_KEY, request_timeout=120)
21
 
 
15
  # define the parser object
16
  parser = JsonOutputParser()
17
 
18
+ def jobdes2text(jobdes: str) -> str:
19
  # setup the gemini pro
20
  llm = ChatGoogleGenerativeAI(model="gemini-pro", temperature=0.3, convert_system_message_to_human=True, api_key=GOOGLE_API_KEY, request_timeout=120)
21
 
data/.gitkeep DELETED
File without changes
requirements.txt CHANGED
@@ -67,7 +67,7 @@ protobuf==4.25.3
67
  pyasn1==0.5.1
68
  pyasn1-modules==0.3.0
69
  pycparser==2.21
70
- pydantic==2.6.3
71
  pydantic-extra-types==2.6.0
72
  pydantic-settings==2.2.1
73
  pydantic_core==2.16.3
@@ -76,6 +76,7 @@ pyparsing==3.1.2
76
  python-docx==1.1.0
77
  python-dotenv==1.0.1
78
  python-multipart==0.0.9
 
79
  PyYAML==6.0.1
80
  qdrant-client==1.8.0
81
  requests==2.31.0
 
67
  pyasn1==0.5.1
68
  pyasn1-modules==0.3.0
69
  pycparser==2.21
70
+ pydantic==2.6.3
71
  pydantic-extra-types==2.6.0
72
  pydantic-settings==2.2.1
73
  pydantic_core==2.16.3
 
76
  python-docx==1.1.0
77
  python-dotenv==1.0.1
78
  python-multipart==0.0.9
79
+ pywin32==306
80
  PyYAML==6.0.1
81
  qdrant-client==1.8.0
82
  requests==2.31.0