Spaces:
Sleeping
Sleeping
import gradio as gr | |
import requests | |
import pandas as pd | |
import re | |
import csv | |
import datetime | |
from rapidfuzz import process, fuzz | |
import requests | |
from difflib import get_close_matches | |
from fuzzywuzzy import process | |
bens_df = pd.read_excel('bens_tab.xlsx') | |
data_crawler = pd.read_csv('data_crawler.csv', index_col=False) | |
data_crawler = data_crawler[['Title', 'Price', 'Currency', 'Condition', 'Link', 'Marketplace']] | |
def fetch_data_to_dataframe(query, limit=50, source="mercadolibre"): | |
if source == "mercadolibre": | |
BASE_URL = "https://api.mercadolibre.com/sites/MLB/search" | |
params = {'q': query, 'limit': limit} | |
response = requests.get(BASE_URL, params=params) | |
if response.status_code == 200: | |
data = response.json() | |
if 'results' in data: | |
items = data['results'] | |
df = pd.DataFrame(items) | |
df = df[['title', 'price', 'currency_id', 'condition', 'permalink']] | |
df.columns = ['Title', 'Price', 'Currency', 'Condition', 'Link'] | |
df['Marketplace'] = "Mercado Livre" | |
return df | |
return pd.DataFrame() | |
def refinar_resultados(df): | |
df['Title'] = df['Title'].astype(str) | |
df_refinado = df[~df['Title'].str.contains("kit", case=False, na=False)] | |
padrao_unidades = r'\b(\d+)\s*(unidade|unidades|pacote|pacotes|caixa|caixas)\b' | |
df_refinado = df_refinado[~df_refinado['Title'].str.contains(padrao_unidades, case=False, regex=True, na=False)] | |
return df_refinado | |
def get_best_match(query, choices, limit=15): | |
matches = process.extract(query, choices, scorer=fuzz.WRatio, limit=limit) | |
return [match[0] for match in matches if match[1] > 30] | |
def filtrar_itens_similares(df, termo_pesquisa, limit=15): | |
titulos = df['Title'].tolist() | |
# Use RapidFuzz for improved performance and fuzzy matching | |
titulos_similares = get_best_match(termo_pesquisa, titulos, limit=limit) | |
df_filtrado = df[df['Title'].isin(titulos_similares)] | |
return df_filtrado | |
def calcular_fator_avaliacao(titulo, EC, PU): | |
# Buscar VU e VR baseado no título | |
filtered_df = bens_df[bens_df['TITULO'] == titulo] | |
if filtered_df.empty: | |
raise ValueError(f"Nenhum bem encontrado com o título: {titulo}") | |
bem_info = filtered_df.iloc[0] | |
VU = bem_info['VIDA_UTIL'] | |
VR = bem_info['VALOR_RESIDUAL'] | |
pontuacoes = {'Excelente': 10, 'Bom': 8, 'Regular': 5, 'Péssimo': 2} | |
ec_pontuacao = pontuacoes[EC] | |
PU = float(PU) | |
PVU = 10 - ((PU - 1) * (10 / VU)) | |
PVU = min(PVU, 10) | |
PUB = 10 - (((VU - PU) - 1) * (10 / VU)) | |
PUB = min(PUB, 10) | |
fator_avaliacao = max((4 * ec_pontuacao + 6 * PVU - 3 * PUB) / 100, VR) | |
return fator_avaliacao | |
def select_nearest_items(df): | |
mode_prices = df['Price'].mode() | |
if len(mode_prices) > 0: | |
target_price = mode_prices.min() # Choose the smallest mode if multiple | |
else: | |
target_price = df['Price'].median() # Fallback to median if no mode | |
df['Distance'] = (df['Price'] - target_price).abs() | |
df_sorted = df.sort_values('Distance') | |
included_marketplaces = set() | |
nearest_items = [] | |
for _, row in df_sorted.iterrows(): | |
if row['Marketplace'] not in included_marketplaces: | |
nearest_items.append(row) | |
included_marketplaces.add(row['Marketplace']) | |
if len(included_marketplaces) >= 5: | |
break | |
return pd.DataFrame(nearest_items) | |
def search_with_fallback(query, df, limit=15): | |
# Split the query into parts | |
query_parts = query.split() | |
# Start with the most specific search (full query) | |
specificities = [ | |
" ".join(query_parts[i:]) for i in range(len(query_parts)) | |
] | |
for specificity in specificities: | |
df_filtrado = filtrar_itens_similares(df, specificity, limit=limit) | |
if not df_filtrado.empty: | |
# If we find results at this level of specificity, return them | |
return df_filtrado | |
# If no results are found at any level of specificity, return an empty DataFrame | |
return pd.DataFrame() | |
def integrated_app(query, titulo, EC, PU): | |
df_mercadolibre = fetch_data_to_dataframe(query, 50, "mercadolibre") | |
df_combined = pd.concat([df_mercadolibre, data_crawler], ignore_index=True) | |
if df_combined.empty: | |
return "Nenhum dado encontrado. Tente uma consulta diferente.", pd.DataFrame() | |
df_refined = refinar_resultados(df_combined) | |
# Use the new search_with_fallback function | |
df_similares = search_with_fallback(query, df_refined) | |
if df_similares.empty: | |
return "Nenhum item similar encontrado.", pd.DataFrame() | |
else: | |
df_nearest = select_nearest_items(df_similares) | |
mean_price = df_nearest['Price'].mean() | |
fator_avaliacao = calcular_fator_avaliacao(titulo, EC, PU) | |
valor_avaliacao = mean_price * fator_avaliacao | |
return f"Valor Médio do Bem: R$ {mean_price:.2f}, Fator de Avaliação: {fator_avaliacao*100:.2f}%, Valor de Avaliação: R$ {valor_avaliacao:.2f}", df_nearest | |
titulos = bens_df['TITULO'].unique().tolist() | |
iface = gr.Interface(fn=integrated_app, | |
inputs=[gr.Textbox(label="Digite sua consulta"), | |
gr.Dropdown(label="Classificação Contábil do Bem", choices=titulos, value="MOBILIÁRIO EM GERAL"), | |
gr.Radio(label="Estado de Conservação do Bem", choices=['Excelente', 'Bom', 'Regular', 'Péssimo'], value="Excelente"), | |
gr.Number(label="Período utilizado (anos)", value=1) | |
], | |
outputs=[gr.Textbox(label="Cálculo"), gr.Dataframe(label="Resultados da Pesquisa")], | |
theme=gr.themes.Monochrome(), | |
title = "<span style='color: gray; font-size: 48px;'>Avaliação de Bens Móveis</span>", | |
description=f""" | |
<p style="text-align: left;"><b><span style='color: gray; font-size: 40px;'>aval</span><span style='color: black; font-size: 40px;'>ia</span><span style='color: gray; font-size: 40px;'>.se</b></p> | |
""") | |
iface.launch() | |