# �� Copilot �ͦ� import gradio as gr import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots import json from datetime import datetime from rental_analyzer import RentalAnalyzer from data_generator import generate_mock_rental_data, get_market_summary_stats # �]�w�r��]Hugging Face Spaces �ۮe�^ try: plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'Arial'] plt.rcParams['axes.unicode_minus'] = False except Exception: pass # �����r��]�w���~ def analyze_rental_data(sample_size, use_hf_models): """���毲�Τ��R���D���""" try: # �T�O sample_size �����ļƭ� if sample_size is None or sample_size <= 0: sample_size = 50 # �B�J1: �ͦ�������� progress_info = "? ���b�ͦ����R���..." data = generate_mock_rental_data(int(sample_size)) df = pd.DataFrame(data) if df.empty: raise ValueError("�ͦ�����Ƭ���") # �B�J2: ������R progress_info = "? ���b����έp���R..." analyzer = RentalAnalyzer(df, use_hf_models=use_hf_models) results = analyzer.run_analysis() # �B�J3: �ͦ����i progress_info = "? ���b�ͦ����R���i..." # �򥻲έp���i report = generate_text_report(results) # �ͦ��Ϫ� charts = create_analysis_charts(df, results) # ��ƪ��� display_df = df[['title', 'price', 'area', 'price_per_ping', 'address']].head(10) return ( report, charts['price_distribution'], charts['area_vs_price'], charts['price_range_pie'], charts['keywords_bar'], display_df ) except Exception as e: error_msg = f"���R�L�{���o�Ϳ��~: {str(e)}" empty_fig = px.scatter(title="�L���") empty_df = pd.DataFrame() return ( error_msg, empty_fig, empty_fig, empty_fig, empty_fig, empty_df ) def generate_text_report(results): """�ͦ���r���i""" report = """ # ? ���������s�ϯ��Υ������R���i **���R�ɶ�**: {analysis_time} **��ƨӷ�**: 591���κ�������� ## ? �������p - **�`�����**: {total_properties} �� - **���R�d��**: ���������s�� 2�о�h�q��j�� ## ? �����έp���R - **��������**: {mean_price:,} �� - **���������**: {median_price:,} �� - **�����зǮt**: {std_price:,} �� - **�����d��**: {min_price:,} - {max_price:,} �� - **�Ĥ@�|�����**: {q25_price:,} �� - **�ĤT�|�����**: {q75_price:,} �� ## ? �W�Ʋέp���R - **�����W��**: {mean_area:.1f} �W - **�W�Ƥ����**: {median_area:.1f} �W - **�W�ƽd��**: {min_area:.1f} - {max_area:.1f} �W ## ? �C�W�������R - **�����C�W����**: {mean_ppp:,} ��/�W - **�C�W���������**: {median_ppp:,} ��/�W - **�C�W�����d��**: {min_ppp:,} - {max_ppp:,} ��/�W ## ? �����}�� {insights} ## ? ����ij 1. ���s��2�йq��j�ӯ������Ǹ���í�w 2. ��ij�����w��]�w�b {q25_price:,} - {q75_price:,} ���϶� 3. �C�W�������b {ppp_range} ��/�W�d�� 4. ��ij�M��30�W���k������A�ŦX�����D�y�ݨD 5. ���s�ϾF����N�]�B�R�e�����I�A�㦳�}�n���ͬ����� --- *�����i�� Hugging Face Spaces �۰ʥͦ�* """.format( analysis_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"), total_properties=results['basic_stats']['total_properties'], mean_price=results['basic_stats']['price_stats']['mean'], median_price=results['basic_stats']['price_stats']['median'], std_price=results['basic_stats']['price_stats']['std'], min_price=results['basic_stats']['price_stats']['min'], max_price=results['basic_stats']['price_stats']['max'], q25_price=results['basic_stats']['price_stats']['q25'], q75_price=results['basic_stats']['price_stats']['q75'], mean_area=results['basic_stats']['area_stats']['mean'], median_area=results['basic_stats']['area_stats']['median'], min_area=results['basic_stats']['area_stats']['min'], max_area=results['basic_stats']['area_stats']['max'], mean_ppp=results['basic_stats']['price_per_ping_stats']['mean'], median_ppp=results['basic_stats']['price_per_ping_stats']['median'], min_ppp=results['basic_stats']['price_per_ping_stats']['min'], max_ppp=results['basic_stats']['price_per_ping_stats']['max'], ppp_range=f"{int(results['basic_stats']['price_per_ping_stats']['min'])} - {int(results['basic_stats']['price_per_ping_stats']['max'])}", insights="\n".join([f"{i+1}. {insight}" for i, insight in enumerate(results.get('insights', []))]) ) return report def create_analysis_charts(df, results): """�Ыؤ��R�Ϫ�""" charts = {} # 1. ���������� charts['price_distribution'] = px.histogram( df, x='price', nbins=20, title='����������', labels={'price': '���� (��)', 'count': '����ƶq'}, color_discrete_sequence=['skyblue'] ) charts['price_distribution'].update_layout( xaxis_title="���� (��)", yaxis_title="����ƶq" ) # 2. �W��vs�������I�� charts['area_vs_price'] = px.scatter( df, x='area', y='price', hover_data=['title'], title='�W�ƻP�������Y', labels={'area': '�W��', 'price': '���� (��)'}, color_discrete_sequence=['coral'] ) # �K�[�Ͷսu z = np.polyfit(df['area'], df['price'], 1) line_x = [df['area'].min(), df['area'].max()] line_y = [z[0] * x + z[1] for x in line_x] charts['area_vs_price'].add_trace( go.Scatter( x=line_x, y=line_y, mode='lines', name='�Ͷսu', line=dict(color='red', dash='dash') ) ) # 3. �����϶����� price_dist = df['price_range'].value_counts() charts['price_range_pie'] = px.pie( values=price_dist.values, names=price_dist.index, title='�����϶�����', color_discrete_sequence=px.colors.qualitative.Set3 ) # 4. ����r���R������ if 'keywords_analysis' in results and results['keywords_analysis']: keywords_data = results['keywords_analysis'] filtered_keywords = {k: v for k, v in keywords_data.items() if v > 0} if filtered_keywords: charts['keywords_bar'] = px.bar( x=list(filtered_keywords.values()), y=list(filtered_keywords.keys()), orientation='h', title='����y�z����r�W�v', labels={'x': '�X�{����', 'y': '����r'}, color_discrete_sequence=['lightcoral'] ) else: charts['keywords_bar'] = px.bar(title="�L����r���") else: charts['keywords_bar'] = px.bar(title="�L����r���") return charts # �Ы�Gradio���� def create_interface(): """�Ы�Gradio�ϥΪ̤���""" with gr.Blocks( title="591���Τ��R�� - ���������s��", theme=gr.themes.Soft(), css=""" .main-header { text-align: center; color: #2E86AB; } .info-box { background-color: #f0f8ff; padding: 15px; border-radius: 10px; } """ ) as demo: # ���D gr.Markdown( """ # ? 591���Τ��R�� - ���������s�� ### �M�~���Υ������R�u�� | ��X Hugging Face �ͺA�t�� ���R�ؼСG**���������s��** | **2�о�h�q��j��** """, elem_classes=["main-header"] ) # �\�໡�� with gr.Row(): gr.Markdown( """
### ? ���R�\�� - ? **�����έp**: �����ȡB����ơB�������R - ? **�W�Ƥ��R**: �W�ƻP�������Y���Q - ? **�ʻ���**: �C�W�����έp���R - ? **�����Ͷ�**: �����϶������Ϫ� - ? **��r���R**: ����y�z����r���� - ? **AI�ҫ�**: ��XHugging Face�۵M�y���B�z
""", elem_classes=["info-box"] ) # ����O with gr.Row(): with gr.Column(scale=1): gr.Markdown("### ?? ���R�]�w") sample_size = gr.Slider( minimum=30, maximum=100, value=50, step=10, label="? ��Ƶ���", info="���R�����Ϊ���ƶq" ) use_hf_models = gr.Checkbox( value=True, label="? �ϥ� Hugging Face �ҫ�", info="�ҥ�AI��r���R�\��" ) analyze_btn = gr.Button( "? �}�l���R", variant="primary", size="lg" ) # ���G��ܰϰ� gr.Markdown("---") gr.Markdown("## ? ���R���G") with gr.Tabs(): # ���R���i���� with gr.Tab("? ���R���i"): report_output = gr.Markdown() # ��ı�ƹϪ����� with gr.Tab("? ��ı�ƹϪ�"): with gr.Row(): price_dist_plot = gr.Plot(label="����������") area_price_plot = gr.Plot(label="�W�ƻP�������Y") with gr.Row(): price_pie_plot = gr.Plot(label="�����϶�����") keywords_plot = gr.Plot(label="����r���R") # ��ƪ��歶�� with gr.Tab("? ��Ƥ@��"): data_table = gr.Dataframe( headers=["����W��", "����", "�W��", "�C�W����", "�a�}"], label="���θ�ƪ� (�e10��)", interactive=False ) # �]�w���s�ƥ� analyze_btn.click( fn=analyze_rental_data, inputs=[sample_size, use_hf_models], outputs=[ report_output, price_dist_plot, area_price_plot, price_pie_plot, keywords_plot, data_table ] ) # ������T gr.Markdown( """ --- ### ? �ϥλ��� 1. �վ���R�Ѽơ]��Ƶ��ơBAI�ҫ��ﶵ�^ 2. �I���u�}�l���R�v���s 3. �d�ݤ��R���i�B�Ϫ��M��ƪ��� 4. �Ҧ����R���G��������ơA�Ȩѥܽd�ϥ� ### ?? �`�N�ƶ� - ��ƨӷ��������ͦ��A�Ω�i�ܤ��R�\�� - ��ڳ��p�ɥi�걵�u�ꪺ591���κ�API - �ϥ�Hugging Face�ҫ��i��ݭn�����B�z�ɶ� **? �� Hugging Face Spaces ���Ѥ䴩 | �ϥ� GitHub Copilot �ͦ�** """ ) return demo # �D�{�� if __name__ == "__main__": # �פJnumpy�]�ץ����e����|�^ import numpy as np demo = create_interface() demo.launch()