Spaces:
Sleeping
Sleeping
Download src/idea_functions.py from GGGIS/GGGISfolio: direct link, hf CLI and curl.
- Browser
- Download file 15.5 kB
-
https://huggingface.co/spaces/GGGIS/GGGISfolio/resolve/main/src/idea_functions.py
- Command line
-
hf download hf://spaces/GGGIS/GGGISfolio/src/idea_functions.py
-
curl -L -o idea_functions.py https://huggingface.co/spaces/GGGIS/GGGISfolio/resolve/main/src/idea_functions.py
15.5 kB
| import pandas as pd | |
| import src.data_manager as dm | |
| from src.openai_client import create_openai_client | |
| from src.node_functions import get_nodes_dataframe | |
| from datetime import datetime | |
| import pytz | |
| import gradio as gr | |
| try: | |
| from gradio import SelectData | |
| except ImportError: | |
| # Gradio ๋ฒ์ ์ด ๋ฎ์ ๊ฒฝ์ฐ | |
| SelectData = None | |
| def generate_idea_with_chatgpt( | |
| contest_title, | |
| contest_theme, | |
| contest_description, | |
| contest_context="", | |
| search_text="", | |
| selected_tenants=None, | |
| selected_tags=None, | |
| ): | |
| """ChatGPT๋ฅผ ์ด์ฉํด ์์ด๋์ด ์์ฑ (ํํฐ๋ง๋ ๋ ธ๋ ์ฌ์ฉ)""" | |
| if not contest_title or not contest_theme or not contest_description: | |
| return ( | |
| "๊ณต๋ชจ์ ์ ๋ชฉ, ์ฃผ์ , ์ค๋ช ์ ๋ชจ๋ ์ ๋ ฅํด์ฃผ์ธ์.", | |
| contest_title, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง | |
| contest_theme, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง | |
| contest_description, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง | |
| contest_context, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง | |
| ) | |
| try: | |
| # OpenAI ํด๋ผ์ด์ธํธ ์์ฑ (.env์์ API ํค ์๋ ๋ก๋) | |
| client = create_openai_client() | |
| # ๊ณต๋ชจ์ ์ ๋ณด ๊ตฌ์ฑ | |
| contest_info = { | |
| "title": contest_title, | |
| "theme": contest_theme, | |
| "description": contest_description, | |
| "context": contest_context, | |
| } | |
| # ํํฐ๋ง๋ ๋ ธ๋๋ค ๊ฐ์ ธ์ค๊ธฐ | |
| filtered_nodes = get_filtered_nodes( | |
| search_text, selected_tenants, selected_tags | |
| ) | |
| # ๋๋ฒ๊น ์ ๋ณด ์ถ๋ ฅ | |
| print(f"[ChatGPT ๋๋ฒ๊ทธ] ํํฐ๋ง๋ ๋ ธ๋ ์: {len(filtered_nodes)}") | |
| print( | |
| f"[ChatGPT ๋๋ฒ๊ทธ] ๊ฒ์์ด: '{search_text}', ํ ๋ํธ: {selected_tenants}, ํ๊ทธ: {selected_tags}" | |
| ) | |
| # ์์ด๋์ด ์์ฑ | |
| generated_idea = client.generate_idea(contest_info, filtered_nodes) | |
| if "error" in generated_idea: | |
| return ( | |
| generated_idea["error"], | |
| "", # contest_title ๋น์ฐ๊ธฐ | |
| "", # contest_theme ๋น์ฐ๊ธฐ | |
| "", # contest_description ๋น์ฐ๊ธฐ | |
| "", # contest_context ๋น์ฐ๊ธฐ | |
| ) | |
| # ์ฌ์ฉ๋ ๋ ธ๋์ ํํฐ ์ ๋ณด ์ถ๊ฐ | |
| generated_idea["used_nodes"] = filtered_nodes | |
| generated_idea["used_filters"] = { | |
| "search_text": search_text or "", | |
| "selected_tenants": selected_tenants or [], | |
| "selected_tags": selected_tags or [], | |
| "total_nodes_available": len(dm.nodes_data), | |
| "filtered_nodes_count": len(filtered_nodes), | |
| } | |
| # ์์ฑ์ผ์ ๋ฐ ๊ณ ์ ID ์ถ๊ฐ (ํ๊ตญ ์๊ฐ) | |
| kst = pytz.timezone("Asia/Seoul") | |
| current_time = datetime.now(kst) | |
| generated_idea["id"] = current_time.strftime("%Y%m%d%H%M%S") + str( | |
| len(dm.ideas_data) | |
| ) | |
| generated_idea["created_at"] = current_time.strftime("%Y-%m-%d %H:%M:%S") | |
| generated_idea["created_date"] = current_time.strftime("%Y-%m-%d") | |
| generated_idea["created_time"] = current_time.strftime("%H:%M:%S") | |
| dm.ideas_data.append(generated_idea) | |
| try: | |
| dm.save_ideas() | |
| except Exception as save_error: | |
| return ( | |
| f"์์ด๋์ด ์์ฑ์ ์๋ฃ๋์์ง๋ง ์ ์ฅ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {save_error}", | |
| "", # contest_title ๋น์ฐ๊ธฐ | |
| "", # contest_theme ๋น์ฐ๊ธฐ | |
| "", # contest_description ๋น์ฐ๊ธฐ | |
| "", # contest_context ๋น์ฐ๊ธฐ | |
| ) | |
| return ( | |
| f"์์ด๋์ด '{generated_idea['title']}'๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์์ต๋๋ค!", | |
| "", # contest_title ๋น์ฐ๊ธฐ | |
| "", # contest_theme ๋น์ฐ๊ธฐ | |
| "", # contest_description ๋น์ฐ๊ธฐ | |
| "", # contest_context ๋น์ฐ๊ธฐ | |
| ) | |
| except Exception as e: | |
| return ( | |
| f"์์ด๋์ด ์์ฑ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {str(e)}", | |
| "", # contest_title ๋น์ฐ๊ธฐ | |
| "", # contest_theme ๋น์ฐ๊ธฐ | |
| "", # contest_description ๋น์ฐ๊ธฐ | |
| "", # contest_context ๋น์ฐ๊ธฐ | |
| ) | |
| def get_ideas_dataframe(search_text=""): | |
| """์์ฑ๋ ์์ด๋์ด๋ค์ ๋ฐ์ดํฐํ๋ ์์ผ๋ก ๋ณํ (์ต์ ์ ์ ๋ ฌ, ๊ฒ์ ์ง์)""" | |
| columns = [ | |
| "์์ฑ์ผ์", | |
| "๊ณต๋ชจ์ ์ ๋ชฉ", | |
| "์์ด๋์ด ์ ๋ชฉ", | |
| "์์ด๋์ด ๊ฐ์", | |
| "AI ์ด๋ฆ", | |
| ] | |
| if not dm.ideas_data: | |
| return pd.DataFrame(columns=columns) | |
| # ์์ฑ์ผ์ ๊ธฐ์ค์ผ๋ก ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ (์ต์ ์์ด๋์ด๊ฐ ์๋ก) | |
| sorted_ideas = sorted( | |
| dm.ideas_data, | |
| key=lambda x: x.get("created_at", "1900-01-01 00:00:00"), | |
| reverse=True, | |
| ) | |
| df_data = [] | |
| for idx, idea in enumerate(sorted_ideas): | |
| # ์๋ณธ ๋ฐฐ์ด์์์ ์ค์ ์ธ๋ฑ์ค ์ฐพ๊ธฐ | |
| original_index = dm.ideas_data.index(idea) | |
| # ๊ณต๋ชจ์ ์ ๋ชฉ ์ถ์ถ (contest_info ๋์ ๋๋ฆฌ์์) | |
| contest_title = "N/A" | |
| if idea.get("contest_info") and isinstance(idea.get("contest_info"), dict): | |
| contest_title = idea.get("contest_info", {}).get("title", "N/A") | |
| # ๊ฒ์ ํํฐ ์ ์ฉ (๊ณต๋ชจ์ ์ ๋ชฉ ๋๋ ์์ด๋์ด ์ ๋ชฉ์์ ๊ฒ์) | |
| if search_text: | |
| idea_title = idea.get("title", "").lower() | |
| contest_title_search = contest_title.lower() | |
| search_lower = search_text.lower() | |
| # ๊ณต๋ชจ์ ์ ๋ชฉ์ด๋ ์์ด๋์ด ์ ๋ชฉ ์ค ํ๋๋ผ๋ ๊ฒ์์ด๋ฅผ ํฌํจํ์ง ์์ผ๋ฉด ์ ์ธ | |
| if not (search_lower in idea_title or search_lower in contest_title_search): | |
| continue | |
| df_data.append( | |
| { | |
| "์์ฑ์ผ์": idea.get("created_at", "N/A"), | |
| "๊ณต๋ชจ์ ์ ๋ชฉ": contest_title, | |
| "์์ด๋์ด ์ ๋ชฉ": idea.get("title", "์ ๋ชฉ ์์"), | |
| "์์ด๋์ด ๊ฐ์": idea.get("overview", "๊ฐ์ ์์"), | |
| "AI ์ด๋ฆ": idea.get("ai_name", "Unknown"), | |
| "_original_index": original_index, # ์จ๊ฒจ์ง ์๋ณธ ์ธ๋ฑ์ค | |
| } | |
| ) | |
| # ํํฐ๋ง ๊ฒฐ๊ณผ๊ฐ ์์ด๋ ์ปฌ๋ผ๋ช ์ด ์ ์ง๋๋๋ก ๋น DataFrame ๋ฐํ | |
| if not df_data: | |
| return pd.DataFrame(columns=columns) | |
| df = pd.DataFrame(df_data) | |
| # _original_index ์ปฌ๋ผ์ UI์์ ๋ณด์ด์ง ์๋๋ก ์ฒ๋ฆฌ | |
| return df[["์์ฑ์ผ์", "๊ณต๋ชจ์ ์ ๋ชฉ", "์์ด๋์ด ์ ๋ชฉ", "์์ด๋์ด ๊ฐ์", "AI ์ด๋ฆ"]] | |
| def filter_ideas(search_text): | |
| """์์ด๋์ด ๊ฒ์ (๊ณต๋ชจ์ ์ ๋ชฉ ๋๋ ์์ด๋์ด ์ ๋ชฉ์์ ๊ฒ์)""" | |
| df = get_ideas_dataframe(search_text) | |
| return gr.update(value=df) | |
| def get_idea_details(selection_data): | |
| """์ ํ๋ ์์ด๋์ด์ ์์ธ ์ ๋ณด ๋ฐํ""" | |
| try: | |
| # selection_data๊ฐ None์ด๊ฑฐ๋ ๋น์ด์๋ ๊ฒฝ์ฐ | |
| if selection_data is None: | |
| return "์์ด๋์ด๋ฅผ ์ ํํด์ฃผ์ธ์.", "", "", "", "", "", "" | |
| # Gradio dataframe.select()๋ SelectData ๊ฐ์ฒด๋ฅผ ์ ๋ฌํจ | |
| selected_index = None | |
| # SelectData ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ (Gradio v4+) | |
| if SelectData and isinstance(selection_data, SelectData): | |
| if hasattr(selection_data, "index") and isinstance( | |
| selection_data.index, (list, tuple) | |
| ): | |
| selected_index = selection_data.index[0] # ํ ์ธ๋ฑ์ค | |
| # hasattr๋ก index ์์ฑ ํ์ธ (์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ) | |
| elif hasattr(selection_data, "index"): | |
| if isinstance(selection_data.index, (list, tuple)): | |
| selected_index = selection_data.index[0] # ํ ์ธ๋ฑ์ค | |
| elif ( | |
| hasattr(selection_data.index, "__len__") | |
| and len(selection_data.index) > 0 | |
| ): | |
| selected_index = selection_data.index[0] | |
| # ๋์ ๋๋ฆฌ ํํ์ธ ๊ฒฝ์ฐ | |
| elif isinstance(selection_data, dict): | |
| if "index" in selection_data: | |
| if isinstance(selection_data["index"], (list, tuple)): | |
| selected_index = selection_data["index"][0] | |
| else: | |
| selected_index = selection_data["index"] | |
| # ์ ์ ๊ฐ์ด ์ง์ ์ ๋ฌ๋ ๊ฒฝ์ฐ | |
| elif isinstance(selection_data, (int, float)): | |
| selected_index = int(selection_data) | |
| # ์ธ๋ฑ์ค๋ฅผ ์ฐพ์ง ๋ชปํ ๊ฒฝ์ฐ | |
| if selected_index is None: | |
| return "์์ด๋์ด๋ฅผ ์ ํํด์ฃผ์ธ์.", "", "", "", "", "", "" | |
| except Exception as e: | |
| return "์์ด๋์ด ์ ํ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.", "", "", "", "", "", "" | |
| if selected_index >= len(dm.ideas_data): | |
| return "์ ํ๋ ์์ด๋์ด๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.", "", "", "", "", "", "" | |
| idea = dm.ideas_data[selected_index] | |
| title = idea.get("title", "์ ๋ชฉ ์์") | |
| problem = idea.get("problem", "๋ฌธ์ ์์ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| solution = idea.get("solution", "์๋ฃจ์ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| implementation = idea.get("implementation", "๊ตฌํ๋ฐฉ์ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| expected_effect = idea.get("expected_effect", "๊ธฐ๋ํจ๊ณผ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| # ๊ณต๋ชจ์ ์ ๋ณด ๋ฐ ์์ฑ์ผ์ | |
| contest_info = idea.get("contest_info", {}) | |
| created_at = idea.get("created_at", "N/A") | |
| contest_details = f"""๊ณต๋ชจ์ ์ ๋ชฉ: {contest_info.get('title', 'N/A')} | |
| ์ฃผ์ : {contest_info.get('theme', 'N/A')} | |
| ์ค๋ช : {contest_info.get('description', 'N/A')} | |
| ๋งฅ๋ฝ: {contest_info.get('context', 'N/A')}""" | |
| return ( | |
| title, | |
| contest_details, | |
| problem, | |
| solution, | |
| implementation, | |
| expected_effect, | |
| created_at, | |
| ) | |
| def get_idea_details_by_index(selected_index): | |
| """์ธ๋ฑ์ค๋ฅผ ์ง์ ๋ฐ์์ ์์ด๋์ด ์์ธ ์ ๋ณด ๋ฐํ""" | |
| try: | |
| if selected_index is None or selected_index < 0: | |
| return "์ฌ๋ฐ๋ฅด์ง ์์ ์ธ๋ฑ์ค์ ๋๋ค.", "", "", "", "", "", "" | |
| if selected_index >= len(dm.ideas_data): | |
| return "์ ํ๋ ์์ด๋์ด๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.", "", "", "", "", "", "" | |
| idea = dm.ideas_data[selected_index] | |
| title = idea.get("title", "์ ๋ชฉ ์์") | |
| problem = idea.get("problem", "๋ฌธ์ ์์ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| solution = idea.get("solution", "์๋ฃจ์ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| implementation = idea.get("implementation", "๊ตฌํ๋ฐฉ์ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| expected_effect = idea.get("expected_effect", "๊ธฐ๋ํจ๊ณผ ์ ๋ณด๊ฐ ์์ต๋๋ค.") | |
| # ๊ณต๋ชจ์ ์ ๋ณด ๋ฐ ์์ฑ์ผ์ | |
| contest_info = idea.get("contest_info", {}) | |
| created_at = idea.get("created_at", "N/A") | |
| contest_details = f"""๊ณต๋ชจ์ ์ ๋ชฉ: {contest_info.get('title', 'N/A')} | |
| ์ฃผ์ : {contest_info.get('theme', 'N/A')} | |
| ์ค๋ช : {contest_info.get('description', 'N/A')} | |
| ๋งฅ๋ฝ: {contest_info.get('context', 'N/A')}""" | |
| # ์ฌ์ฉ๋ ๋ ธ๋ ์ ๋ณด ํฌ๋งทํ | |
| used_nodes = idea.get("used_nodes", []) | |
| nodes_info = "" | |
| if used_nodes: | |
| nodes_list = [] | |
| for i, node in enumerate(used_nodes, 1): | |
| nodes_list.append( | |
| f"{i}. {node.get('title', '์ ๋ชฉ ์์')} ({node.get('tenant', '๋ฏธ์ง์ ')})" | |
| ) | |
| nodes_info = "\n".join(nodes_list) | |
| else: | |
| nodes_info = "์ฌ์ฉ๋ ๋ ธ๋ ์ ๋ณด๊ฐ ์์ต๋๋ค." | |
| # ์ฌ์ฉ๋ ํํฐ ์ ๋ณด ํฌ๋งทํ | |
| used_filters = idea.get("used_filters", {}) | |
| filters_info = f"""๊ฒ์์ด: {used_filters.get('search_text', '์์')} | |
| ์ ํ๋ ํ ๋ํธ: {', '.join(used_filters.get('selected_tenants', [])) or '์์'} | |
| ์ ํ๋ ํ๊ทธ: {', '.join(used_filters.get('selected_tags', [])) or '์์'} | |
| ์ ์ฒด ๋ ธ๋ ์: {used_filters.get('total_nodes_available', 0)} | |
| ํํฐ๋ง๋ ๋ ธ๋ ์: {used_filters.get('filtered_nodes_count', 0)}""" | |
| # ์์ด๋์ด ์์ฑ ๊ทผ๊ฑฐ (๊ธฐ์กด ์์ด๋์ด๋ rationale ํ๋๊ฐ ์์ ์ ์์) | |
| rationale = idea.get("rationale", "") | |
| if not rationale: | |
| rationale = "์ด ์์ด๋์ด๋ ์ด์ ๋ฒ์ ์์ ์์ฑ๋์ด ๊ทผ๊ฑฐ ์ ๋ณด๊ฐ ์์ต๋๋ค." | |
| return ( | |
| title, | |
| contest_details, | |
| problem, | |
| solution, | |
| implementation, | |
| expected_effect, | |
| created_at, # ์์ฑ์ผ์๋ฅผ ๋ณ๋ ๋ฐํ | |
| nodes_info, # ์ฌ์ฉ๋ ๋ ธ๋ ์ ๋ณด | |
| filters_info, # ์ฌ์ฉ๋ ํํฐ ์ ๋ณด | |
| rationale, # ์์ด๋์ด ์์ฑ ๊ทผ๊ฑฐ | |
| ) | |
| except Exception as e: | |
| print(f"[ERROR] get_idea_details_by_index ์๋ฌ: {e}") | |
| return ( | |
| "์์ด๋์ด ์ ๋ณด ๋ก๋ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.", | |
| "", | |
| "", | |
| "", | |
| "", | |
| "", | |
| "", | |
| "", | |
| "", | |
| "", | |
| ) | |
| def refresh_ideas(): | |
| """์์ด๋์ด ๋ชฉ๋ก ์๋ก๊ณ ์นจ""" | |
| dm.load_ideas() | |
| return get_ideas_dataframe() | |
| def clear_ideas(): | |
| """๋ชจ๋ ์์ด๋์ด ์ญ์ """ | |
| dm.ideas_data = [] | |
| dm.save_ideas() | |
| return get_ideas_dataframe() | |
| def delete_idea(selected_index): | |
| """์ ํ๋ ์์ด๋์ด ์ญ์ """ | |
| if selected_index is None or selected_index >= len(dm.ideas_data): | |
| return "์ญ์ ํ ์์ด๋์ด๋ฅผ ์ ํํด์ฃผ์ธ์.", get_ideas_dataframe() | |
| deleted_idea = dm.ideas_data.pop(selected_index) | |
| dm.save_ideas() | |
| return ( | |
| f"์์ด๋์ด '{deleted_idea.get('title', '์ ๋ชฉ ์์')}'๊ฐ ์ญ์ ๋์์ต๋๋ค.", | |
| get_ideas_dataframe(), | |
| ) | |
| # ์ถ๊ฐ: Gemini API ์ฐ๋์ ์ํ ์ค๋น ํจ์ | |
| def generate_idea_with_gemini( | |
| contest_title, | |
| contest_theme, | |
| contest_description, | |
| contest_context="", | |
| search_text="", | |
| selected_tenants=None, | |
| selected_tags=None, | |
| ): | |
| """Gemini๋ฅผ ์ด์ฉํด ์์ด๋์ด ์์ฑ (ํฅํ ๊ตฌํ ์์ )""" | |
| # ํํฐ๋ง๋ ๋ ธ๋ ์ ๋ณด๋ ๋ก๊ทธ๋ก ์ถ๋ ฅ (๋๋ฒ๊น ์ฉ) | |
| filtered_nodes = get_filtered_nodes(search_text, selected_tenants, selected_tags) | |
| print(f"[Gemini ๋๋ฒ๊ทธ] ํํฐ๋ง๋ ๋ ธ๋ ์: {len(filtered_nodes)}") | |
| return ( | |
| "Gemini API ์ฐ๋์ ์์ง ๊ตฌํ๋์ง ์์์ต๋๋ค.", | |
| contest_title, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง (์์ง ๊ตฌํ๋์ง ์์์ผ๋ฏ๋ก) | |
| contest_theme, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง | |
| contest_description, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง | |
| contest_context, # ์ ๋ ฅ๋ ๊ฐ ์ ์ง | |
| ) | |
| def get_filtered_nodes(search_text="", selected_tenants=None, selected_tags=None): | |
| """ํํฐ๋ง ์กฐ๊ฑด์ ๋ง๋ ๋ ธ๋๋ค์ ๋ฐํ""" | |
| if not dm.nodes_data: | |
| return [] | |
| filtered_nodes = [] | |
| for node in dm.nodes_data: | |
| # ํ ์คํธ ๊ฒ์ ํํฐ (๋ ธ๋ ์ด๋ฆ์์ ๊ฒ์) | |
| if search_text and search_text.lower() not in node["title"].lower(): | |
| continue | |
| # ํ ๋ํธ ํํฐ | |
| if selected_tenants and node.get("tenant", "๋ฏธ์ง์ ") not in selected_tenants: | |
| continue | |
| # ํ๊ทธ ํํฐ (์ ํ๋ ํ๊ทธ ์ค ํ๋๋ผ๋ ํฌํจ๋์ด์ผ ํจ) | |
| if selected_tags: | |
| node_tags = node.get("tags", []) | |
| if not any(tag in node_tags for tag in selected_tags): | |
| continue | |
| filtered_nodes.append(node) | |
| return filtered_nodes | |