Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -28,7 +28,6 @@ def process_files(files):
|
|
28 |
|
29 |
knowledge_text = ""
|
30 |
for file in files:
|
31 |
-
# ... (código de extração de texto de PDF/TXT permanece o mesmo) ...
|
32 |
file_path = file.name
|
33 |
if file_path.endswith(".pdf"):
|
34 |
try:
|
@@ -80,99 +79,86 @@ def find_info(question, knowledge_state):
|
|
80 |
|
81 |
question_embedding = retriever_model.encode(question, convert_to_tensor=True)
|
82 |
cosine_scores = util.cos_sim(question_embedding, knowledge_base_embeddings)
|
83 |
-
top_k = min(5, len(knowledge_base))
|
84 |
top_results = torch.topk(cosine_scores, k=top_k, dim=-1)
|
85 |
retrieved_context = "\n---\n".join([knowledge_base[i] for i in top_results.indices[0]])
|
86 |
|
87 |
-
prompt = f"### Instruction:\nExtraia a informação exata para responder à pergunta com base no contexto. Seja direto.\n\nContexto:\n{retrieved_context}\n\nPergunta:\n{question}\n\n### Response:"
|
88 |
|
89 |
input_ids = generator_tokenizer(prompt, return_tensors="pt").input_ids
|
90 |
-
outputs = generator_model.generate(input_ids, max_new_tokens=
|
91 |
answer = generator_tokenizer.decode(outputs[0, input_ids.shape[1]:], skip_special_tokens=True)
|
92 |
return answer.strip()
|
93 |
|
94 |
|
95 |
# --- 4. O CÉREBRO DO AGENTE: evaluate_document ---
|
96 |
-
def evaluate_document(task, knowledge_state):
|
97 |
"""Esta é a função principal do agente. Ela orquestra as chamadas à ferramenta 'find_info'
|
98 |
-
para construir um relatório de avaliação completo."""
|
99 |
if not task:
|
100 |
-
return "Por favor, forneça uma tarefa de avaliação."
|
101 |
if not knowledge_state or not knowledge_state[0] or knowledge_state[1] is None:
|
102 |
-
return "⚠️ A base de conhecimento está vazia. Por favor, processe alguns ficheiros primeiro."
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
-
#
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
thought_process += f" - Resultado: {result_info}\n"
|
118 |
-
thought_process += f" - Incerteza: {uncertainty_info}\n\n"
|
119 |
-
|
120 |
-
# Passo 3: Validade
|
121 |
-
thought_process += "Passo 3: A verificar as datas...\n"
|
122 |
-
calibration_date = find_info("Qual foi a data em que a calibração foi realizada?", knowledge_state)
|
123 |
-
due_date = find_info("Qual a data de vencimento ou próxima calibração?", knowledge_state)
|
124 |
-
thought_process += f" - Data da Calibração: {calibration_date}\n"
|
125 |
-
thought_process += f" - Data de Vencimento: {due_date}\n\n"
|
126 |
-
|
127 |
-
# Passo 4: Geração do Relatório Final
|
128 |
-
thought_process += "Passo 4: A compilar o relatório final...\n"
|
129 |
-
final_prompt = f"""### Instruction:
|
130 |
-
Você é um auditor de metrologia a escrever um relatório de avaliação. Com base nos 'Dados Recolhidos' abaixo, escreva um parecer técnico conciso e estruturado.
|
131 |
-
|
132 |
-
**Dados Recolhidos:**
|
133 |
-
- Cliente: {client_info}
|
134 |
-
- Instrumento: {instrument_info}
|
135 |
-
- Resultado da Calibração: {result_info}
|
136 |
-
- Incerteza de Medição: {uncertainty_info}
|
137 |
-
- Data da Execução: {calibration_date}
|
138 |
-
- Próxima Calibração: {due_date}
|
139 |
-
|
140 |
-
### Response:
|
141 |
-
**Relatório de Avaliação do Certificado**
|
142 |
-
|
143 |
-
**1. Identificação:**
|
144 |
-
- **Cliente:** [Preencha com o cliente]
|
145 |
-
- **Instrumento:** [Preencha com o instrumento]
|
146 |
-
|
147 |
-
**2. Análise Técnica:**
|
148 |
-
- **Resultado:** [Preencha com o resultado]
|
149 |
-
- **Incerteza:** [Preencha com a incerteza]
|
150 |
-
- **Conformidade:** [Comente brevemente se o resultado 'Aprovado' é consistente com os dados]
|
151 |
-
|
152 |
-
**3. Validade:**
|
153 |
-
- **Data da Calibração:** [Preencha com a data]
|
154 |
-
- **Validade:** [Preencha com a data de vencimento]
|
155 |
-
|
156 |
-
**4. Parecer Final:**
|
157 |
-
- [Escreva uma frase de conclusão sobre a validade e aceitabilidade do certificado com base nos dados.]
|
158 |
-
"""
|
159 |
-
|
160 |
-
input_ids = generator_tokenizer(final_prompt, return_tensors="pt").input_ids
|
161 |
-
outputs = generator_model.generate(input_ids, max_new_tokens=400, do_sample=False, pad_token_id=generator_tokenizer.eos_token_id)
|
162 |
-
final_report = generator_tokenizer.decode(outputs[0, input_ids.shape[1]:], skip_special_tokens=True)
|
163 |
-
|
164 |
-
thought_process += "Avaliação concluída."
|
165 |
-
return thought_process, final_report
|
166 |
|
167 |
# --- 5. Interface Gráfica (Atualizada para o Agente) ---
|
168 |
with gr.Blocks(theme=gr.themes.Soft()) as interface:
|
169 |
knowledge_state = gr.State()
|
170 |
gr.Markdown(
|
171 |
"""
|
172 |
-
# 🤖 Agente de
|
173 |
-
**1. Carregue um documento**: Envie um certificado de calibração
|
174 |
**2. Processe o documento**: Clique no botão para criar a base de conhecimento.
|
175 |
-
**3. Inicie a
|
176 |
"""
|
177 |
)
|
178 |
|
@@ -183,17 +169,14 @@ with gr.Blocks(theme=gr.themes.Soft()) as interface:
|
|
183 |
status_box = gr.Textbox(label="Status do Processamento", interactive=False)
|
184 |
|
185 |
with gr.Column(scale=2):
|
186 |
-
task_box = gr.Textbox(label="Tarefa de
|
187 |
-
submit_button = gr.Button("Iniciar
|
188 |
|
189 |
with gr.Row():
|
190 |
-
|
191 |
-
thought_box = gr.Textbox(label="Passos do Agente", interactive=False, lines=15)
|
192 |
-
with gr.Column():
|
193 |
-
report_box = gr.Textbox(label="Relatório Final de Avaliação", interactive=False, lines=15)
|
194 |
|
195 |
process_button.click(fn=process_files, inputs=[file_uploader], outputs=[knowledge_state, status_box])
|
196 |
-
submit_button.click(fn=evaluate_document, inputs=[task_box, knowledge_state], outputs=[
|
197 |
|
198 |
# --- 6. Lançamento do App ---
|
199 |
if __name__ == "__main__":
|
|
|
28 |
|
29 |
knowledge_text = ""
|
30 |
for file in files:
|
|
|
31 |
file_path = file.name
|
32 |
if file_path.endswith(".pdf"):
|
33 |
try:
|
|
|
79 |
|
80 |
question_embedding = retriever_model.encode(question, convert_to_tensor=True)
|
81 |
cosine_scores = util.cos_sim(question_embedding, knowledge_base_embeddings)
|
82 |
+
top_k = min(5, len(knowledge_base))
|
83 |
top_results = torch.topk(cosine_scores, k=top_k, dim=-1)
|
84 |
retrieved_context = "\n---\n".join([knowledge_base[i] for i in top_results.indices[0]])
|
85 |
|
86 |
+
prompt = f"### Instruction:\nExtraia a informação exata para responder à pergunta com base no contexto. Se a informação não for encontrada, responda 'Não encontrado'. Seja direto.\n\nContexto:\n{retrieved_context}\n\nPergunta:\n{question}\n\n### Response:"
|
87 |
|
88 |
input_ids = generator_tokenizer(prompt, return_tensors="pt").input_ids
|
89 |
+
outputs = generator_model.generate(input_ids, max_new_tokens=150, do_sample=False, pad_token_id=generator_tokenizer.eos_token_id)
|
90 |
answer = generator_tokenizer.decode(outputs[0, input_ids.shape[1]:], skip_special_tokens=True)
|
91 |
return answer.strip()
|
92 |
|
93 |
|
94 |
# --- 4. O CÉREBRO DO AGENTE: evaluate_document ---
|
95 |
+
def evaluate_document(task, knowledge_state, progress=gr.Progress(track_tqdm=True)):
|
96 |
"""Esta é a função principal do agente. Ela orquestra as chamadas à ferramenta 'find_info'
|
97 |
+
para construir um relatório de avaliação completo, seguindo uma checklist."""
|
98 |
if not task:
|
99 |
+
return "Por favor, forneça uma tarefa de avaliação."
|
100 |
if not knowledge_state or not knowledge_state[0] or knowledge_state[1] is None:
|
101 |
+
return "⚠️ A base de conhecimento está vazia. Por favor, processe alguns ficheiros primeiro."
|
102 |
+
|
103 |
+
# Checklist de avaliação baseada na sua solicitação
|
104 |
+
checklist = {
|
105 |
+
"1. Incerteza de Medição": [
|
106 |
+
("1.1 a 1.2 Casas Decimais / Compatibilidade", "Qual a incerteza de medição declarada e o número de casas decimais dos resultados?"),
|
107 |
+
("1.3 Nível de Confiança, Fator de Abrangência (k) e Graus de Liberdade", "Qual o nível de confiança, fator de abrangência (k) e graus de liberdade declarados para a incerteza?"),
|
108 |
+
("1.4 Declaração de Rastreabilidade dos Resultados", "Existe uma declaração de que os resultados se referem somente aos itens calibrados?")
|
109 |
+
],
|
110 |
+
"2. Resultados da Calibração": [
|
111 |
+
("2.1 a 2.3 Unidades SI, Casas Decimais e Algarismos Significativos", "Os resultados da calibração são apresentados com unidades do Sistema Internacional (SI)? Qual o mensurando e a quantidade de algarismos significativos?"),
|
112 |
+
],
|
113 |
+
"3. Conformidade da Faixa": [
|
114 |
+
("3.1 Faixa e Especificações Solicitadas", "A calibração foi realizada na faixa de utilização especificada ou solicitada?")
|
115 |
+
],
|
116 |
+
"4. Condições Ambientais": [
|
117 |
+
("4.1 Registro das Condições e Incerteza Associada", "Quais foram as condições ambientais (temperatura, umidade) registadas durante a calibração? Há menção de incerteza associada a elas?")
|
118 |
+
],
|
119 |
+
"5. Identificação do Item": [
|
120 |
+
("5.1 Descrição e Identificação do Item", "Qual a descrição completa e identificação do item calibrado (nome, fabricante, tipo, modelo, número de série)?")
|
121 |
+
],
|
122 |
+
"6. Identificação do Método": [
|
123 |
+
("6.1 Método/Procedimento Utilizado", "Qual o método ou procedimento de calibração utilizado?")
|
124 |
+
],
|
125 |
+
"7. Identificação do Cliente": [
|
126 |
+
("7.1 Nome e Endereço do Cliente", "Qual o nome e o endereço do cliente/contratante?")
|
127 |
+
],
|
128 |
+
"8. Identificação do Laboratório": [
|
129 |
+
("8.1 Nome e Endereço do Laboratório", "Qual o nome e o endereço do laboratório que emitiu o certificado?")
|
130 |
+
],
|
131 |
+
"9. Identificação do Certificado": [
|
132 |
+
("9.1 Número do Certificado", "Qual o número de identificação unívoca do certificado?")
|
133 |
+
],
|
134 |
+
"10. Autorização": [
|
135 |
+
("10.1 Pessoas Autorizadas", "Quem são os responsáveis (nome e função) pela emissão ou assinatura do certificado?")
|
136 |
+
]
|
137 |
+
}
|
138 |
+
|
139 |
+
report = f"# Relatório de Análise de Conformidade\n\n**Tarefa:** {task}\n\n---\n\n"
|
140 |
|
141 |
+
# Itera sobre a checklist, fazendo perguntas ao documento para cada item
|
142 |
+
for section, questions in progress.tqdm(checklist.items(), desc="A avaliar documento..."):
|
143 |
+
report += f"## {section}\n\n"
|
144 |
+
for sub_item, question in questions:
|
145 |
+
# O agente "pergunta" ao documento
|
146 |
+
answer = find_info(question, knowledge_state)
|
147 |
+
# Adiciona a resposta ao relatório
|
148 |
+
report += f"**{sub_item}:**\n{answer}\n\n"
|
149 |
+
report += "---\n\n"
|
150 |
+
|
151 |
+
return report
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
|
153 |
# --- 5. Interface Gráfica (Atualizada para o Agente) ---
|
154 |
with gr.Blocks(theme=gr.themes.Soft()) as interface:
|
155 |
knowledge_state = gr.State()
|
156 |
gr.Markdown(
|
157 |
"""
|
158 |
+
# 🤖 Agente de Análise de Conformidade Metrológica
|
159 |
+
**1. Carregue um documento**: Envie um certificado de calibração (`.pdf` ou `.txt`).
|
160 |
**2. Processe o documento**: Clique no botão para criar a base de conhecimento.
|
161 |
+
**3. Inicie a Análise**: Dê uma tarefa ao agente (ex: "Analisar conformidade deste certificado") e clique em "Iniciar Análise".
|
162 |
"""
|
163 |
)
|
164 |
|
|
|
169 |
status_box = gr.Textbox(label="Status do Processamento", interactive=False)
|
170 |
|
171 |
with gr.Column(scale=2):
|
172 |
+
task_box = gr.Textbox(label="Tarefa de Análise", placeholder='Ex: Avaliar a conformidade deste certificado de calibração.')
|
173 |
+
submit_button = gr.Button("Iniciar Análise", variant="primary")
|
174 |
|
175 |
with gr.Row():
|
176 |
+
report_box = gr.Markdown(label="Relatório Final de Análise")
|
|
|
|
|
|
|
177 |
|
178 |
process_button.click(fn=process_files, inputs=[file_uploader], outputs=[knowledge_state, status_box])
|
179 |
+
submit_button.click(fn=evaluate_document, inputs=[task_box, knowledge_state], outputs=[report_box])
|
180 |
|
181 |
# --- 6. Lançamento do App ---
|
182 |
if __name__ == "__main__":
|