File size: 7,731 Bytes
7987d77
 
 
 
 
 
 
 
 
 
d36cfea
7987d77
 
 
 
 
2510e9d
7987d77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d36cfea
 
7987d77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d36cfea
7987d77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed3d9c4
 
 
 
 
 
7987d77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed3d9c4
 
 
 
 
 
 
 
 
 
 
7987d77
 
 
77c8f22
 
d64ccfa
7987d77
 
 
a8767ed
d36cfea
 
7987d77
 
 
a8767ed
d36cfea
7987d77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
import gradio as gr
import pandas as pd
from langchain.memory import VectorStoreRetrieverMemory
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.document_loaders import PyPDFLoader
from langchain_core.prompts import PromptTemplate
import chromadb
import os
from uuid import uuid4
from langchain_google_genai import ChatGoogleGenerativeAI

# Initialize persistent client
CHROMA_PATH = "./vectordb-chroma/gformdb"
os.makedirs(CHROMA_PATH, exist_ok=True)

def process_files(csv_file, gemini_key, user_aspek, pdf_file, model):
    try:
        context = ""

        def context_search(query="a",source_name=False, k=5):

            if source_name==True:
                results = vectorstore.similarity_search(
                    query=query,
                    k=k,
                    filter={"source": source_name}
                )
            else:
                results = vectorstore.similarity_search(
                    query=query,
                    k=k,
                )
            for res in results:
                page_content = res.page_content
                metadata = res.metadata
            return page_content, metadata

        def format_qa_efficient(data_path):
            data = pd.read_csv(data_path)
            data.head()
            qa_efficient = ""
            indexs = 0
            Question = ""
            for column in data.columns[3:]:  # Lewati kolom Timestamp, Email Address, dan Nama
                qa_efficient += f"Nomor-{indexs+1}.{column}:\n"
                indexs += 1
                Question += column
                for index, row in data.iterrows():
                    name = row['Nama']
                    email = row["Email_Address"]
                    answer = row[column]
                    qa_efficient += f"- {name}|{email}: {answer}\n"
                
                qa_efficient += "\n"  # Baris kosong antara setiap pertanyaan

            return qa_efficient, Question

        # Set OpenAI API
        if gemini_key == "":
            gemini_key = os.getenv('GEMINI_API_KEY')
            
        
        # Process CSV (Gradio provides the file path directly)

        QA, Question = format_qa_efficient(csv_file)

        if pdf_file:
            # Initialize Chroma client
            persistent_client = chromadb.PersistentClient(path=CHROMA_PATH)
            collection = persistent_client.get_or_create_collection("RAG")
            
            vectorstore = Chroma(
                client=persistent_client,
                collection_name=collection.name,
                embedding_function=OpenAIEmbeddings()
            )
            
            res, metadata = context_search(pdf_file,k=1)

            if metadata == pdf_file.name:
                # Process PDF (Gradio provides the file path directly)
                pages = PyPDFLoader(pdf_file.name).load_and_split()
                uuids = [str(uuid4()) for _ in range(len(pages))]
                vectorstore.add_documents(documents=pages, ids=uuids)
            context, metadata = context_search(Question, pdf_file.name)

        elif pdf_file == False:
            context = "Tidak ada context tambahan yang diberikan, tolong gunakan pengetahuan anda untuk menjawab pertanyaan"
        
        # Evaluation template
        TEMPLATE = """
        Kamu adalah AI evaluator pendidikan. Nilai jawaban siswa berikut menggunakan panduan ini:

        Buat output dengan format(format ini untuk satu murid, jadi selesaikan dulu 1 murid untuk semua nomor, baru ke murid berikutnya):
        HASIL EVALUASI
        =============
        Nama dan Email Murid: 
        [Nomor Soal].
        Nilai: [Sesuaikan dengan Aspek Penilaian yang diberikan user]
        Alasan: [alasan singkat penilaian]
        Saran Perbaikan: [saran]

        [buat seperti di atas untuk setiap jawaban]

        ================
        Rata-rata Nilai: [nilai]
        
        Rekomendasi Umum:
        [rekomendasi]
        

        MATERI REFERENSI:
        {context}   

        SOAL & JAWABAN:
        {QA}

        Aspek Penilaian yang diberikan user:
        {Aspek}


        """
        
        PROMPT = PromptTemplate(
            input_variables=["QA", "context", "Aspek"],
            template=TEMPLATE
        )
        
        # Initialize ChatGPT
        chat = ChatGoogleGenerativeAI(model=model, api_key=gemini_key)
        chain = PROMPT | chat
        
        # Generate evaluation
        Aspek_penilaian = user_aspek
        
        response = chain.invoke({
            "Aspek": Aspek_penilaian,
            "QA": QA,
            "context": context
        })
        
        return response.content
        
    except Exception as e:
        return f"Error occurred: {str(e)}\nType: {type(e)}"

def load_demo_files(checked):
    if checked:
        return gr.update(value="./demo.csv"), gr.update(value="./demo.pdf")
    else:
        return gr.update(value=None), gr.update(value=None)
        
# Create Gradio interface
def create_interface():
    with gr.Blocks(title="Quiz Evaluator", theme=gr.themes.Soft()) as app:
        with gr.Column(scale=1):
            gr.Markdown(
                """
                # 📝 Quiz Response Evaluator
                Upload your quiz responses (CSV) and reference material (PDF) to get AI-powered evaluation.
                """
            )
            
            with gr.Row():
                with gr.Column(scale=1):
                    csv_input = gr.File(
                        label="Quiz Responses (CSV)",
                        file_types=[".csv"]
                    )
                with gr.Column(scale=1):
                    pdf_input = gr.File(
                        label="Reference Material (PDF)",
                        file_types=[".pdf"]
                    )
                    
            demo_checkbox = gr.Checkbox(
                label="Use Demo Files",
                value=False
            )

            demo_checkbox.change(
                fn=load_demo_files,
                inputs=[demo_checkbox],
                outputs=[csv_input, pdf_input]
            )

            user_aspek = gr.Textbox(
                label="Aspek",
                placeholder="isi dengan bagaimana cara AI akan menilai jawaban",
                show_copy_button=True,
                value = "Jika Jawaban salah berikan nilai 0, jika jawaban benar namun tidak tepat berikan nilai 50, jika jawaban benar dan lengkap serta penjelasan baik, beri nilai 100"
            )

            model_name = gr.Textbox(
                label="Gemini Model",
                placeholder="input your Gemini model",
                value="gemini-1.5-pro"
            )
            
            api_key = gr.Textbox(
                label="Gemini API Key",
                placeholder="Enter your Gemini API key, default is my API key, use it wisely XD",
                type="password"
            )
            
            submit_btn = gr.Button(
                "Evaluate Responses", 
                variant="primary",
                size="lg"
            )
            
            # Using Textbox instead of Markdown for better formatting
            output = gr.Textbox(
                label="Evaluation Results",
                lines=20,
                max_lines=30,
                show_copy_button=True
            )

        
        submit_btn.click(
            fn=process_files,
            inputs=[csv_input,api_key,user_aspek,pdf_input,model_name],
            outputs=output
        )
        
    return app

# Launch the interface
if __name__ == "__main__":
    app = create_interface()
    app.launch(share=True)