Calculo do response_time com template ou transferência.

This commit is contained in:
2026-05-07 08:49:51 -03:00
parent a4ad969176
commit 93346a98ad

View File

@@ -126,7 +126,6 @@ fn main() -> anyhow::Result<()> {
};
// Get the current day in the format YYYY-MM-DD
let current_date = chrono::Local::now();
let formatted_date = current_date.format("%Y-%m-%d").to_string();
@@ -232,9 +231,9 @@ fn main() -> anyhow::Result<()> {
))
.expect("Failed to create response_time.csv");
}
*/
// Read system prompt
let prompt = std::fs::read_to_string("PROMPT.txt").unwrap();
let filter_file_contents = std::fs::read_to_string("FILTER.txt").unwrap_or(String::new());
@@ -318,7 +317,6 @@ fn main() -> anyhow::Result<()> {
let template_id = message_object["is_template"]
.as_bool()
.unwrap_or(true);
// println!("Conteudo do template_id da mensagem {}: {:?}", pos, template_id);
let found = message.find(
"Atendimento transferido para a fila [NovaNet -> Atendimento -> NOC - Clientes]",
);
@@ -373,12 +371,6 @@ fn main() -> anyhow::Result<()> {
.find(&keyword.to_uppercase())
.is_some()
});
/*
let found2 = message_object["is_template"]
.as_bool()
.unwrap_or(true);
let found = found1 || found2;
*/
found1
});
@@ -390,115 +382,103 @@ fn main() -> anyhow::Result<()> {
return Some(json);
});
// Calculate the response time in seconds
let response_time = filtered_chats
.clone()
.map(|messages| {
let json = messages.unwrap();
let talk_histories = &json["talk_histories"];
// find the bot transfer message
let bot_transfer_message = talk_histories
.as_array()
.expect("Wrong message type received from talk histories")
.into_iter()
.enumerate()
.filter(|(pos, message_object)| {
let user_name = message_object["user"]["name"]
.as_str()
.expect("Failed to decode message as string");
user_name == "PipeBot".to_string()
})
.find(|(pos, message_object)| {
let message = message_object["message"]
.as_str()
.expect("Failed to decode message as string");
let found = message.find("Atendimento entregue da fila de espera para o agente [NOC");
let is_template = message_object["is_template"]
.as_bool()
.unwrap_or(true);
found.is_some() || is_template
});
// Find first agent message sent after the last bot message
// let (pos, transfer_message) =
// bot_transfer_message.expect("Failed to get the transfer bot message position");
//INICIO do response time consideranto template ou transferência.
let response_time = filtered_chats
.clone()
.map(|messages| {
let json = messages.unwrap();
let talk_histories = &json["talk_histories"];
let histories = talk_histories.as_array()
.expect("Wrong message type received from talk histories");
let (pos, transfer_message) = match bot_transfer_message {
Some((pos, msg)) => (pos, msg),
None => return "".to_string(), // Retorna string vazia em vez de panic
};
// 1. Encontrar o primeiro gatilho na ordem cronológica (percorrendo do índice mais alto para o mais baixo)
let trigger = histories.iter().enumerate().rev().find(|(_, msg)| {
let is_template = msg["is_template"].as_bool().unwrap_or(false);
let user = msg["user"]["name"].as_str().unwrap_or("");
let message = msg["message"].as_str().unwrap_or("");
let is_transfer = user == "PipeBot"
&& message.contains("Atendimento entregue da fila de espera para o agente [NOC");
is_template || is_transfer
});
let (trigger_pos, trigger_msg) = match trigger {
Some(pair) => pair,
None => return "".to_string(),
};
// 2. Determinar se é transferência (para escolher a referência correta)
let is_transfer_case = {
let user = trigger_msg["user"]["name"].as_str().unwrap_or("");
let message = trigger_msg["message"].as_str().unwrap_or("");
user == "PipeBot"
&& message.contains("Atendimento entregue da fila de espera para o agente [NOC")
};
let (ref_pos, ref_msg) = if is_transfer_case {
// Caso transferência: referência é o próprio gatilho
(trigger_pos, trigger_msg)
} else {
// Caso template: referência é a próxima mensagem cronológica (índice trigger_pos - 1)
if trigger_pos > 0 {
match histories.get(trigger_pos - 1) {
Some(next_msg) => (trigger_pos - 1, next_msg),
None => return "".to_string(),
}
} else {
return "".to_string(); // template na última posição (sem resposta do cliente)
}
};
// 3. Procurar a primeira resposta do agente após a referência (índices menores que ref_pos)
let agent_msg = (0..ref_pos).rev()
.filter_map(|i| {
let m = &histories[i];
if m["type"].as_str() == Some("out")
&& m["user"]["name"].as_str().map_or(false, |name| name.starts_with("NOC -"))
{
Some(m)
} else {
None
}
})
.take(1)
.collect::<Vec<_>>();
if agent_msg.is_empty() {
return "".to_string();
}
let agent_first_message = agent_msg[0];
// 4. Calcular tempo entre referência e primeira resposta do agente
let format = "%Y-%m-%d %H:%M:%S";
let t_ref = chrono::NaiveDateTime::parse_from_str(
ref_msg["sent_at"].as_str().unwrap(),
format,
).expect("Erro ao parsear data da referência");
let t_agent = chrono::NaiveDateTime::parse_from_str(
agent_first_message["sent_at"].as_str().unwrap(),
format,
).expect("Erro ao parsear data do agente");
let response_time = (t_agent - t_ref).num_seconds() as f32;
let name = agent_first_message["user"]["name"].as_str().unwrap().to_owned();
let id = json["tracking_number"].as_str().unwrap_or("").to_owned();
let ref_date = ref_msg["sent_at"].as_str().unwrap().to_owned();
let agent_date = agent_first_message["sent_at"].as_str().unwrap().to_owned();
println!("response_time: {}s", response_time);
format!(
"{};{};{};{};{}",
name, id, response_time, ref_date, agent_date
)
})
.filter(|s| !s.is_empty())
.reduce(|acc, e| format!("{}\n{}", acc, e))
.unwrap_or("".to_string());
//FIM do response time considerando template ou transferência.
let msg = talk_histories
.as_array()
.expect("Wrong message type received from talk histories")
.into_iter()
.take(pos)
.rev()
.filter(|message| {
message["type"] == "out".to_string()
// && message["user"]["name"] != "PipeBot".to_string()
&& message["user"]["name"].as_str().map_or(false, |name| name.starts_with("NOC -"))
})
.take(1)
.collect_vec();
// Se não encontrar mensagem do agente, retorna string vazia
if msg.is_empty() {
return "".to_string();
}
let agent_first_message = msg[0];
// Calculate time difference between bot message and agent message
let date_user_message_sent = agent_first_message["sent_at"].as_str().unwrap();
let format = "%Y-%m-%d %H:%M:%S";
let date_user_message_sent_parsed =
match chrono::NaiveDateTime::parse_from_str(date_user_message_sent, format) {
Ok(dt) => dt,
Err(e) => {
println!("Error parsing DateTime: {}", e);
panic!("Failed parsing date")
}
};
let date_transfer_message_sent_parsed = match chrono::NaiveDateTime::parse_from_str(
transfer_message["sent_at"].as_str().unwrap(),
format,
) {
Ok(dt) => dt,
Err(e) => {
println!("Error parsing DateTime: {}", e);
panic!("Failed parsing date")
}
};
let response_time = (date_user_message_sent_parsed - date_transfer_message_sent_parsed)
.as_seconds_f32();
let name = agent_first_message["user"]["name"]
.as_str()
.unwrap()
.to_owned();
let id = json["tracking_number"].as_str().unwrap_or("").to_owned();
let bot_transfer_date = date_transfer_message_sent_parsed.to_owned();
let user_response_date = date_user_message_sent.to_owned();
println!(
"response_time: {}s",
(date_user_message_sent_parsed - date_transfer_message_sent_parsed)
.as_seconds_f32()
);
format!(
"{};{};{};{};{}",
name, id, response_time, bot_transfer_date, user_response_date
)
})
.filter(|s| !s.is_empty()) // Filtra strings vazias
.reduce(|acc, e| format!("{}\n{}", acc, e))
.unwrap_or("".to_string());
// return Ok(());
// Open file and write to it
let header = "NOME;ID_TALK;TEMPO DE RESPOSTA;TRANFERENCIA PELO BOT;PRIMEIRA RESPOSTA DO AGENTE";
let mut response_time_file = std::fs::OpenOptions::new()
@@ -535,7 +515,6 @@ fn main() -> anyhow::Result<()> {
message_object["type"],
message_object["user"]["name"]
);
// println!("{}", new_json_filtered);
new_json_filtered
})
.reduce(|acc, e| format!("{acc}\n{e}"))
@@ -551,7 +530,6 @@ fn main() -> anyhow::Result<()> {
serde_json::json!({
"model": OLLAMA_AI_MODEL,
"prompt": format!("{prompt} \n{talk}"),
// "options": serde_json::json!({"temperature": 0.1}),
"stream": false,
})
.to_string(),
@@ -582,8 +560,8 @@ fn main() -> anyhow::Result<()> {
let tracking_number = &json["tracking_number"].as_str().unwrap_or("");
std::fs::write(
format!(
"./evaluations/{}/{} - {} - {}.csv",
formatted_day_before, user_name, talk_id, tracking_number
"./evaluations/{}/{} - {} - {}.csv",
formatted_day_before, user_name, talk_id, tracking_number
//formatted_day, user_name, talk_id, tracking_number
),
csv_response,
@@ -616,12 +594,12 @@ fn main() -> anyhow::Result<()> {
// Send folder to email
let recipients = "Nicolas Borges da Silva <nicolas.borges@nova.net.br>, wilson@nova.net.br";
let recipients = "nicolas.borges@nova.net.br, wilson@nova.net.br";
println!("Trying to send email... Recipients {recipients}");
send_mail_util::send_mail_util::send_email(
&format!("Avaliacao atendimentos da fila NOC - Clientes do dia {formatted_day_before}"),
//&format!("Avaliacao atendimentos da fila Financeiro NVL2 do dia {formatted_day}"),
//&format!("Avaliacao atendimentos da fila NOC - Clientes do dia {formatted_day}"),
&BOT_EMAIL,
&BOT_EMAIL_PASSWORD,
recipients,
@@ -660,7 +638,7 @@ fn get_piperun_chats_on_date(
("report_type", report_type.clone()),
("start_date", formatted_day_before_at_midnight.clone()),
//("start_date", formatted_day_start.clone()),
("end_date", formatted_day_before_at_23_59_59.clone()),
("end_date", formatted_day_before_at_23_59_59.clone()),
//("end_date", formatted_day_end.clone()),
("date_range_type", start_of_talk_code.clone()),
("queue_id[]", support_queue_id.clone()),