Compare commits
4 Commits
7fb6021e64
...
ca406b4601
| Author | SHA1 | Date | |
|---|---|---|---|
| ca406b4601 | |||
| 197642727c | |||
| 99a4c81a58 | |||
| 178219c4df |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@ src/.env
|
||||
.env
|
||||
log/
|
||||
.zip
|
||||
.vscode/
|
||||
evaluations
|
||||
# Added by cargo
|
||||
#
|
||||
|
||||
31
Cargo.lock
generated
31
Cargo.lock
generated
@@ -581,6 +581,27 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938"
|
||||
dependencies = [
|
||||
"csv-core",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debug_unsafe"
|
||||
version = "0.1.3"
|
||||
@@ -1381,9 +1402,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "lettre"
|
||||
version = "0.11.18"
|
||||
version = "0.11.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cb54db6ff7a89efac87dba5baeac57bb9ccd726b49a9b6f21fb92b3966aaf56"
|
||||
checksum = "9e13e10e8818f8b2a60f52cb127041d388b89f3a96a62be9ceaffa22262fef7f"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chumsky",
|
||||
@@ -1836,6 +1857,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"csv",
|
||||
"dotenv",
|
||||
"http",
|
||||
"ipaddress",
|
||||
@@ -1844,6 +1866,7 @@ dependencies = [
|
||||
"polars",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"walkdir",
|
||||
"zip",
|
||||
@@ -4061,9 +4084,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "5.1.1"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f852905151ac8d4d06fdca66520a661c09730a74c6d4e2b0f27b436b382e532"
|
||||
checksum = "eb2a05c7c36fde6c09b08576c9f7fb4cda705990f73b58fe011abf7dfb24168b"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arbitrary",
|
||||
|
||||
@@ -19,9 +19,11 @@ reqwest = { version = "0.12.23", features = ["json", "cookies", "blocking"] }
|
||||
chrono = { version = "0.4.42" }
|
||||
itertools = {version = "0.14.0"}
|
||||
ipaddress = {version = "0.1.3"}
|
||||
zip = { version = "5.1.1"}
|
||||
zip = { version = "6.0.0"}
|
||||
walkdir = { version = "2.5.0"}
|
||||
lettre = {version = "0.11.18", features = ["builder"]}
|
||||
lettre = {version = "0.11.19", features = ["builder"]}
|
||||
anyhow = { version = "1.0.100"}
|
||||
polars = { version = "0.51.0"}
|
||||
serde = { version = "1.0.228" }
|
||||
csv = {version = "1.4.0"}
|
||||
regex = { version = "1.12.2" }
|
||||
@@ -1,8 +1,111 @@
|
||||
Abaixo está a avaliação de um atendimento que foi realizado. Eu preciso que a formatação fique consistente e padronizada.
|
||||
Padronize o arquivo CSV da seguinte forma, deixando apenas as colunas listadas.
|
||||
Título: CATEGORIA;PONTOS
|
||||
A sua resposta deve ser apenas o CSV com a formatação corrigida, nada mais deve ser incluído na sua resposta.
|
||||
Se não for possível padronizar o arquivo de entrada de acordo com as instruções fornecidas a resposta deve ser vazia.
|
||||
As categorias são: APRESENTAÇÃO, CONFIRMAÇÃO DE E-MAIL, CONFIRMAÇÃO DE TELEFONE, PROTOCOLO, USO DO PORTUGUÊS, PACIÊNCIA E EDUCAÇÃO, DISPONIBILIDADE, CONHECIMENTO TÉCNICO, DIDATISMO, ESCLARECIMENTO, TEMPO DE ESPERA
|
||||
A coluna pontos deve ter apenas os valores 0 ou 1, se no arquivo de entrada estiver incorreto a resposta deve ser vazia.
|
||||
A sua resposta deve ser apenas o CSV com a formatação corrigida, nada mais deve ser incluído na sua resposta, nem mesmo notas sobre a resposta.
|
||||
Se não for possível padronizar o arquivo de entrada de acordo com as instruções fornecidas a resposta deve ser o CSV com o campo de pontuação vazio.
|
||||
As categorias são: APRESENTAÇÃO, CONFIRMAÇÃO DE E-MAIL, CONFIRMAÇÃO DE TELEFONE, PROTOCOLO, USO DO PORTUGUÊS, PACIÊNCIA E EDUCAÇÃO, DISPONIBILIDADE, CONHECIMENTO TÉCNICO, DIDATISMO
|
||||
A coluna pontos deve ter apenas os valores 0, 1 ou vazio, se no arquivo de entrada não houver a avaliação da categoria, a columa de pontos deve ser vazia.
|
||||
|
||||
Aqui estão alguns exemplos de formatação de como deve ser a sua resposta:
|
||||
Exemplo 01:
|
||||
Dado o seguinte arquivo de entrada:
|
||||
APRESENTAÇÃO;1;O agente se apresentou ao cliente.;Boa noite, me chamo Ander.;Certo, um bom final de semana! 😊
|
||||
CONFIRMAÇÃO DE E-MAIL;1;O agente pediu confirmação do e-mail.;Para manter o cadastro atualizado, poderia me confirmar se o e-mail continua sendo janainads.sls@gmail.com e se o telefone do titular do cadastro permanece (53) 98446-2208?;Obrigado pela confirmação.
|
||||
CONFIRMAÇÃO DE TELEFONE;1;O agente pediu confirmação do telefone.;Para manter o cadastro atualizado, poderia me confirmar se o e-mail continua sendo janainads.sls@gmail.com e se o telefone do titular do cadastro permanece (53) 98446-2208?;Obrigado pela confirmação.
|
||||
PROTOCOLO;1;O agente informou o protocolo.;Aqui está o protocolo do teu atendimento: 2510.3624;Boa noite, me chamo Ander.
|
||||
USO DO PORTUGUÊS;1;O agente utilizou português correto.;Aqui está o protocolo do teu atendimento: 2510.3624;Para manter o cadastro atualizado, poderia me confirmar se o e-mail continua sendo janainads.sls@gmail.com e se o telefone do titular do cadastro permanece (53) 98446-2208?
|
||||
PACIÊNCIA E EDUCAÇÃO;1;O agente foi paciente e educado.;Obrigado pela confirmação.;Certo, um bom final de semana! 😊
|
||||
DISPONIBILIDADE;1;O agente demonstrou disponibilidade.;Caso tenha alguma dúvida, nos contate. A equipe da NovaNet está sempre aqui para te ajudar.😊;Certo, um bom final de semana! 😊
|
||||
CONHECIMENTO TÉCNICO;1;O agente identificou que não havia problemas nos equipamentos.;Verifiquei aqui os equipamentos e não identifiquei nenhum problema com eles.;A potência recebida pelo equipamento está normal e as configurações do roteador estão todas corretas.
|
||||
DIDATISMO;1;O agente foi didático ao orientar o cliente.;Certo, tu poderia se conectar na rede do primeiro roteador e verificar se ocorre algum problema?;Entendi, pode ser algum problema neste segundo roteador, tu pode estar reiniciando ele na tomada para caso seja algum travamento.
|
||||
100%
|
||||
|
||||
A resposta sua deve ser:
|
||||
```csv
|
||||
CATEGORIA;PONTOS
|
||||
APRESENTAÇÃO;1
|
||||
CONFIRMAÇÃO DE E-MAIL;1
|
||||
CONFIRMAÇÃO DE TELEFONE;1
|
||||
PROTOCOLO;1
|
||||
USO DO PORTUGUÊS;1
|
||||
PACIÊNCIA E EDUCAÇÃO;1
|
||||
DISPONIBILIDADE;1
|
||||
CONHECIMENTO TÉCNICO;1
|
||||
DIDATISMO;1
|
||||
```
|
||||
|
||||
Exemplo 02:
|
||||
Dado o seguinte arquivo de entrada:
|
||||
01,1,Apresentação,"Boa tarde, me chamo Ander. (12:10:05)"
|
||||
02,1,Confirmou e‑mail,"Para manter o cadastro atualizado, poderia me confirmar se o e‑mail continua sendo mmaicomvoss@gmail.com? (13:01:40)"
|
||||
03,1,Confirmou telefone,"para manter o cadastro atualizado, poderia me confirmar se o telefone continua (53) 98414‑3027? (13:01:40)"
|
||||
04,1,Informa protocolo,"Aqui está o protocolo do teu atendimento: 2510.2749 (12:10:06)"
|
||||
05,1,Uso correto do português,"Todas as mensagens foram escritas em português formal e correto, inclusive com 'tu' permitido. (12:10:05‑13:03:08)"
|
||||
06,1,Uso de linguagem paciente e educada,"Aguarde meu retorno, por gentileza; me informe, por gentileza; obrigado pela confirmação. (12:10:13‑13:03:07)"
|
||||
07,1,Disponibilidade expressa,"Caso tenha alguma dúvida, nos contate. A equipe da NovaNet está sempre aqui para te ajudar. (13:03:08)"
|
||||
08,1,Conhecimento técnico,"Identificou mau contato no cabo, instruiu reconexões, avaliou ordem de serviço, cotou peças. (12:25:44‑12:57:10)"
|
||||
09,1,Didático,"Desconecte o cabo LAN/WAN passo a passo e me informe quando terminar. (12:25:56‑12:26:06)"
|
||||
10,1,Eclaração diagnóstica,"Fez diagnóstico de mau contato no cabo e ofereceu ordem de serviço sem custo. (12:55:17‑13:01:15)"
|
||||
11,2,Tempo de espera excedido, 2 ocorrências,"Intervalos superiores a 5 min: 12:55:17‑13:01:15 (5 min 58 s) e 12:27:51‑12:54:11 (26 min 20 s)"
|
||||
|
||||
A resposta sua deve ser:
|
||||
```csv
|
||||
CATEGORIA;PONTOS
|
||||
APRESENTAÇÃO;1
|
||||
CONFIRMAÇÃO DE E-MAIL;1
|
||||
CONFIRMAÇÃO DE TELEFONE;1
|
||||
PROTOCOLO;1
|
||||
USO DO PORTUGUÊS;1
|
||||
PACIÊNCIA E EDUCAÇÃO;1
|
||||
DISPONIBILIDADE;1
|
||||
CONHECIMENTO TÉCNICO;1
|
||||
DIDATISMO;1
|
||||
```
|
||||
|
||||
Exemplo 03:
|
||||
Dado o seguinte arquivo de entrada:
|
||||
Identificação e abertura do atendimento,1,
|
||||
Confirmação de dados do cliente,1,
|
||||
Verificação do histórico e do plano do cliente,1,
|
||||
Análise e diagnóstico da falha na conectividade,1,
|
||||
Verificação e teste de equipamentos,1,
|
||||
Sugestão de solução de conectividade,1,
|
||||
Escala de serviço,1,
|
||||
Encerramento de atendimento,1,
|
||||
Follow-up,1,
|
||||
Comunicação com o cliente,1,
|
||||
Tempo de Resposta,1
|
||||
|
||||
A sua resposta deve ser vazia neste caso, pois a entrada não fornece a pontuação adequada para os critérios.
|
||||
Ou seja o retorno deve ser o seguinte
|
||||
```csv
|
||||
CATEGORIA;PONTOS
|
||||
APRESENTAÇÃO;
|
||||
CONFIRMAÇÃO DE E-MAIL;
|
||||
CONFIRMAÇÃO DE TELEFONE;
|
||||
PROTOCOLO;
|
||||
USO DO PORTUGUÊS;
|
||||
PACIÊNCIA E EDUCAÇÃO;
|
||||
DISPONIBILIDADE;
|
||||
CONHECIMENTO TÉCNICO;
|
||||
DIDATISMO;
|
||||
```
|
||||
|
||||
|
||||
Aqui um exemplo de formatação de como não deve ser sua resposta
|
||||
Erro 01: Não utilizar o formato estritamente como fornecido nas instruções e copiar da entrada que está sendo avaliada
|
||||
```csv
|
||||
CATEGORIA;PONTOS
|
||||
APRESENTAÇÃO;1
|
||||
Confirmação de e-mail;1
|
||||
CONFIRMAÇÃO DE TELEFONE;1
|
||||
PROTOCOLO;1
|
||||
USO DO PORTUGUÊS;1
|
||||
PACIÊNCIA E EDUCAÇÃO;1
|
||||
DISPONIBILIDADE;1
|
||||
CONHECIMENTO TÉCNICO;1
|
||||
DIDATISMO;1
|
||||
```
|
||||
|
||||
Abaixo está a avaliação que deve ser processada
|
||||
--------------------------------
|
||||
|
||||
@@ -2,12 +2,35 @@ use std::fmt::Debug;
|
||||
|
||||
use chrono::Datelike;
|
||||
use itertools::Itertools;
|
||||
use polars::prelude::buffer::validate_utf8;
|
||||
use polars::prelude::*;
|
||||
use reqwest;
|
||||
use walkdir;
|
||||
use std::time::Duration;
|
||||
use std::env;
|
||||
|
||||
use csv;
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct CsvHeader {
|
||||
CATEGORIA: String,
|
||||
PONTOS: Option<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct CsvEvaluation {
|
||||
APRESENTAÇÃO: u8,
|
||||
CONFIRMAÇÃO_DE_EMAIL: u8,
|
||||
CONFIRMAÇÃO_DE_TELEFONE: u8,
|
||||
PROTOCOLO: u8,
|
||||
USO_DO_PORTUGUÊS: u8,
|
||||
PACIÊNCIA_E_EDUCAÇÃO: u8,
|
||||
DISPONIBILIDADE: u8,
|
||||
CONHECIMENTO_TÉCNICO: u8,
|
||||
DIDATISMO: u8,
|
||||
ID_TALK: String
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match dotenv::dotenv().ok() {
|
||||
Some(_) => println!("Environment variables loaded from .env file"),
|
||||
@@ -105,14 +128,15 @@ fn main() {
|
||||
})
|
||||
.take(1)
|
||||
.map(|file_name_csv| {
|
||||
println!("{:?}", file_name_csv.path());
|
||||
let file_contents = std::fs::read_to_string(file_name_csv.path()).expect("Failed to read CSV file");
|
||||
|
||||
println!("{}", format!("{prompt_data_sanitization} \n{file_contents}"));
|
||||
let ollama_api_request = client.post(format!("http://{OLLAMA_SANITIZED_IP}:{OLLAMA_PORT}/api/generate"))
|
||||
.body(
|
||||
serde_json::json!({
|
||||
"model": OLLAMA_AI_MODEL_DATA_SANITIZATION,
|
||||
"prompt": format!("{prompt_data_sanitization} \n{file_contents}"),
|
||||
"temperature": 0.0, // Get predictable and reproducible output
|
||||
"stream": false,
|
||||
}).to_string()
|
||||
);
|
||||
@@ -125,13 +149,65 @@ fn main() {
|
||||
let ai_response = response_json["response"]
|
||||
.as_str()
|
||||
.expect("Failed to get AI response as string");
|
||||
println!("AI Response: {}", ai_response);
|
||||
|
||||
let ai_response = ai_response.to_string();
|
||||
|
||||
let ai_response = if let Some(resp) = ai_response.strip_prefix(" ").unwrap_or(&ai_response).strip_prefix("```csv\n") { resp.to_string() } else { ai_response };
|
||||
let ai_response = if let Some(resp) = ai_response.strip_suffix(" ").unwrap_or(&ai_response).strip_suffix("```") { resp.to_string() } else { ai_response };
|
||||
|
||||
return Ok((ai_response, file_name_csv));
|
||||
|
||||
},
|
||||
Err(error) => {println!("Error {error}");}
|
||||
Err(error) => {println!("Error {error}"); return Err(error);}
|
||||
};
|
||||
|
||||
})
|
||||
.for_each(|value| println!("{:?}", value));
|
||||
.filter_map_ok(|(ai_repsonse, file_path_csv)| {
|
||||
let mut reader = csv::ReaderBuilder::new()
|
||||
.has_headers(true)
|
||||
.delimiter(b';')
|
||||
.from_reader(ai_repsonse.as_bytes());
|
||||
|
||||
let mut deserialized_iter = reader.deserialize::<CsvHeader>();
|
||||
|
||||
let correctly_parsed = deserialized_iter.all(|value| {
|
||||
value.is_ok() && value.unwrap().PONTOS.is_some()
|
||||
});
|
||||
|
||||
if !correctly_parsed { return None; }
|
||||
|
||||
// Parse id talk from file_path
|
||||
// filename example is: CC - Erraoander Quintana - 515578 - 20251020515578.csv
|
||||
// id talk is the last information, so in the example is: 20251020515578
|
||||
let regex_filename = regex::Regex::new(r"(CC - )((\w+\s*)+) - (\d+) - (\d+).csv").unwrap();
|
||||
|
||||
let filename = file_path_csv
|
||||
.file_name()
|
||||
.into_string()
|
||||
.expect("Failed to convert file name as Rust &str");
|
||||
let found_regex_groups_in_filename = regex_filename.captures(
|
||||
filename.as_str()
|
||||
).expect("Failed to do regex capture");
|
||||
|
||||
let talk_id = found_regex_groups_in_filename.get(5).expect("Failed to get the id from regex maches").clone();
|
||||
|
||||
println!("{:?}", talk_id);
|
||||
// a.for_each(|val| { println!("{:?}", val)});
|
||||
|
||||
// println!("{:?}", a);
|
||||
|
||||
// Do validation on CSV parsed
|
||||
// let records_parsed = reader.records();
|
||||
|
||||
// if records_parsed.try_len().expect("Failed to obtain lenght") != 9 { return None; }
|
||||
|
||||
// reader.records().for_each(|record| println!("{:?}", record));
|
||||
|
||||
|
||||
return Some(());
|
||||
|
||||
})
|
||||
.for_each(|_value| {});
|
||||
// println!("{:?}", files_inside_folder_on_date);
|
||||
|
||||
return Some(());
|
||||
|
||||
Reference in New Issue
Block a user