Spaces:
Running
Running
File size: 10,729 Bytes
c5a97b3 c038e47 3c5c245 d4e0320 923fcc9 c5a97b3 99aed09 53ae920 1a5aa7c b4cb87b 99aed09 6003014 3c5c245 2df76af e7525b4 6dec4eb e7525b4 27de34f f906a7c 517f0a7 27de34f e7525b4 27de34f e7525b4 27de34f 6dec4eb 38df220 3c5c245 2598bbd 7a6bd46 2598bbd 601b79b 2598bbd 7a6bd46 1efcf05 2c05d82 905b603 489461c 905b603 1efcf05 905b603 3992853 905b603 5ef4720 2237b4d 5d4f445 94b2524 07df588 78633a0 94b2524 78633a0 5ef4720 78633a0 2237b4d c5a97b3 2fe5b5e d3db32a 601b79b d3db32a 601b79b 99aed09 601b79b aff5c22 f308877 f3ff845 6baa204 2237b4d 94b2524 6baa204 f555ad2 6baa204 f555ad2 6baa204 f555ad2 5ef4720 6baa204 5ef4720 f555ad2 6baa204 2237b4d 5ef4720 2237b4d 2c05d82 2237b4d 7c67564 2c05d82 2237b4d 2c05d82 2237b4d c1badbd 7c67564 ea98fbe 59e4db6 2237b4d 074db95 2237b4d 074db95 2598bbd c5a97b3 2c05d82 ae59a9a 59e4db6 e5b70df 2237b4d 78ac961 f2141ad 2c05d82 2237b4d 601b79b fbf4f69 550146d 94b2524 550146d 2237b4d 601b79b 6003014 3c5c245 99aed09 59e4db6 3bd1e98 f308877 601b79b 4d527e1 fbf4f69 550146d 3c5c245 205d4a0 8352a3e baa4db4 8352a3e 3bd1e98 550146d a4241c5 |
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 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
import gradio as gr
import requests
import pandas as pd
from rapidfuzz import process, fuzz
from docx import Document
from datetime import datetime
from docx.oxml import OxmlElement
from docx.shared import Cm
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 get_report(query, df_nearest):
doc = Document()
# Adding a title
doc.add_heading('RELATÓRIO DE AVALIAÇÃO DE VALOR DE MERCADO – EXP.', level=1)
# Adding some details
doc.add_paragraph('Solicitante:')
doc.add_paragraph('Interessado:')
doc.add_paragraph('Proprietário:')
doc.add_paragraph('Objetivo da Avaliação: Definir o valor de mercado dos bens abaixo discriminados para registro no Patrimônio do Município.')
# Adding section heading and content
doc.add_heading('1. Características do(s) Avaliando(s):', level=2)
doc.add_paragraph('1.1 Avaliando 01:')
doc.add_paragraph(f'Descrição: {query}')
# Add evaluation section
doc.add_heading('2. Avaliação:', level=2)
doc.add_paragraph('2.1 Avaliando 01')
# Add market research section
doc.add_heading('3. Pesquisa de Mercado:', level=2)
# Filter and rename columns in df_nearest
df_nearest_filtered = df_nearest[['ID', 'Title', 'Price', 'Link', 'Marketplace']].copy()
df_nearest_filtered.columns = ['Item', 'Descrição', 'Preço', 'Link', 'Fornecedor']
# Here you'll insert the df_nearest_filtered as a table
if not df_nearest_filtered.empty:
table = doc.add_table(rows=1, cols=len(df_nearest_filtered.columns))
table.style = 'Table Grid'
table.autofit = False
table.allow_autofit = False
table.columns[0].width = Cm(3)
table.rows[0].cells[0].width = Cm(3)
hdr_cells = table.rows[0].cells
for i, column_name in enumerate(df_nearest_filtered.columns):
hdr_cells[i].text = column_name
for index, row in df_nearest_filtered.iterrows():
row_cells = table.add_row().cells
for i, value in enumerate(row):
if i == 3:
row_cells[i].text = str(value)
else:
row_cells[i].text = str(value)
today_date = datetime.now().strftime('%d/%m/%Y')
doc.add_paragraph(f'Lajeado/RS, {today_date}')
doc.add_paragraph('Membros da Comissão:')
# Save the document
doc.save('laudo.docx')
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()
items = data.get('results', [])
df = pd.DataFrame(items)[['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, include_word=[]):
df['Title'] = df['Title'].astype(str)
# Define a list of keywords to exclude, indicating multiples
exclude_keywords = ["kit", "conjunto", "pacote", "caixa", "unidades", "Kits", " e "]
# Add conditional exclusion for words not included in the query
exclude_patterns = [keyword for keyword in exclude_keywords if keyword not in include_word]
# Combine all exclude patterns into a single regex pattern
exclude_pattern = r'\b(' + '|'.join(exclude_patterns) + r')\b|\b(\d+)\s*(unidade|pacotes|caixas)\b'
# Perform the filtering in one operation
df_refinado = df[~df['Title'].str.contains(exclude_pattern, case=False, regex=True, na=False)]
return df_refinado
def get_best_match(query, choices, limit=50):
# Using RapidFuzz for improved performance and fuzzy matching
matches = process.extract(query, choices, scorer=fuzz.WRatio, limit=limit)
return [match[0] for match in matches if match[1] > 75]
def match_query_words_in_titles(query, title):
"""
Check if all words in the query have a close match within the title.
Returns True if all words match to a certain degree; False otherwise.
"""
query_words = query.lower().split()
match_threshold = 75 # Adjust this threshold as needed
for word in query_words:
# Find the best match for each word in the query within the title
match_score = fuzz.partial_ratio(word, title.lower())
if match_score < match_threshold:
return False # If any word doesn't match well enough, return False
return True # All words matched well enough
def filtrar_itens_similares(df, termo_pesquisa, limit=50):
# Apply the match function to each title, filtering for those that match the query words
matches = df['Title'].apply(lambda title: match_query_words_in_titles(termo_pesquisa, title))
df_filtrado = df[matches]
# Further refine the list to the top N matches based on overall similarity to the query
df_filtrado['Overall_Similarity'] = df_filtrado['Title'].apply(lambda title: fuzz.WRatio(termo_pesquisa, title))
df_filtrado = df_filtrado.sort_values('Overall_Similarity', ascending=False).head(limit)
return df_filtrado
def calcular_fator_avaliacao(titulo, EC, PU):
filtered_df = bens_df[bens_df['TITULO'] == titulo]
if filtered_df.empty:
return None # Or handle the error as needed
bem_info = filtered_df.iloc[0]
VU, VR = bem_info['VIDA_UTIL'], bem_info['VALOR_RESIDUAL']
ec_pontuacao = {'Excelente': 10, 'Bom': 8, 'Regular': 5, 'Péssimo': 2}[EC]
PU, PVU, PUB = float(PU), min(10 - ((PU - 1) * (10 / VU)), 10), min(10 - (((VU - PU) - 1) * (10 / VU)), 10)
fator_avaliacao = max((4 * ec_pontuacao + 6 * PVU - 3 * PUB) / 100, VR)
return fator_avaliacao
def select_nearest_items(df, query):
# Lower the title similarity threshold if necessary
df['Title_Similarity'] = df['Title'].apply(lambda x: fuzz.WRatio(query, x))
df_filtered = df[df['Title_Similarity'] > 75] # Adjusted threshold
# Calculate mode price in a more inclusive manner
mode_price = df_filtered['Price'].mode()
if mode_price.empty:
target_price = df_filtered['Price'].median()
else:
target_price = mode_price.min()
df_filtered['Distance'] = (df_filtered['Price'] - target_price).abs()
df_sorted = df_filtered.sort_values(['Distance', 'Title_Similarity'], ascending=[True, False])
# Ensure diversity in marketplaces
marketplaces_selected = set()
results = []
for _, row in df_sorted.iterrows():
if row['Marketplace'] not in marketplaces_selected and len(marketplaces_selected) < 5:
results.append(row)
marketplaces_selected.add(row['Marketplace'])
if len(results) >= 5:
break
return pd.DataFrame(results)
def search_with_fallback(query, df, limit=50):
query_parts = query.split()
include_conjunto = "conjunto" in query.lower()
for i in range(len(query_parts), 0, -1):
simplified_query = " ".join(query_parts[:i])
include_word = ["conjunto"] if include_conjunto else [] # Ensure include_word is a list
df_refinado = refinar_resultados(df, include_word=include_word)
df_filtrado = filtrar_itens_similares(df_refinado, simplified_query, limit=limit)
if not df_filtrado.empty:
return df_filtrado
return pd.DataFrame()
def integrated_app(query, titulo, EC, PU, selected_rows):
include_conjunto = "conjunto" in query.lower()
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()
# Pass whether "conjunto" is part of the original query
include_word = ["conjunto"] if include_conjunto else []
df_refined = refinar_resultados(df_combined, include_word=include_word)
df_similares = search_with_fallback(query, df_refined)
if df_similares.empty:
return "Nenhum item similar encontrado.", pd.DataFrame()
df_nearest = select_nearest_items(df_similares, query)
if df_nearest.empty:
return "Nenhum resultado próximo encontrado.", pd.DataFrame()
if selected_rows.strip():
selected_indices = [int(idx) for idx in selected_rows.split(',') if idx.isdigit()]
df_nearest = df_nearest.iloc[selected_indices]
# After calculating df_nearest and before returning it
df_nearest.reset_index(drop=True, inplace=True)
df_nearest['ID'] = df_nearest.index
# Reorder DataFrame columns to make ID first
column_order = ['ID'] + [col for col in df_nearest.columns if col != 'ID']
df_nearest = df_nearest[column_order]
fator_avaliacao = calcular_fator_avaliacao(titulo, EC, PU)
valor_avaliacao = df_nearest['Price'].mean() * fator_avaliacao
get_report(query, df_nearest)
return f"Valor Médio do Bem: R$ {df_nearest['Price'].mean():.2f}, Fator de Avaliação: {fator_avaliacao*100:.2f}%, Valor de Avaliação: R$ {valor_avaliacao:.2f}", df_nearest, 'laudo.docx'
iface = gr.Interface(fn=integrated_app,
inputs=[gr.Textbox(label="Digite sua consulta"),
gr.Dropdown(label="Classificação Contábil do Bem", choices=bens_df['TITULO'].unique().tolist(), 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),
gr.Textbox(label="IDs das linhas selecionadas (separadas por vírgula)", placeholder="Exemplo: 0,2,5")], # Using Textbox for IDs
outputs=[gr.Textbox(label="Cálculo"), gr.Dataframe(label="Resultados da Pesquisa"), gr.File(label="Laudo de Avaliação")],
theme=gr.themes.Monochrome(),
title=f"""
<p style="text-align: left;">
<b><span style='color: grey; font-size: 50px;'>aval</span><span style='color: orange; font-size: 50px;'>ia</span><span style='color: grey; font-size: 50px;'>.se</span></b>
""",
description="""<p style="text-align: left;">Aplicativo para avaliação de Bens Móveis</p>""")
iface.launch()
|