Spaces:
Running
Running
File size: 53,349 Bytes
c99406b 59177aa c99406b 1df6810 cf8b7b0 e41b021 9a48a94 1df6810 59177aa 79f2daf 59177aa 9a48a94 59177aa fe49aa3 d3caf4c 9a48a94 79f2daf d3caf4c 5eb15fa d3caf4c 22eda88 5eb15fa 59177aa c99406b 9a48a94 71c328b 59177aa 9a48a94 71c328b 9a48a94 71c328b d3caf4c cf8b7b0 59177aa cf8b7b0 d3caf4c cf8b7b0 d3caf4c 79f2daf cf8b7b0 59177aa fe49aa3 59177aa fe49aa3 d3caf4c fe49aa3 59177aa 5eb15fa 59177aa 5eb15fa 59177aa 5eb15fa 59177aa 5eb15fa 59177aa 5eb15fa 59177aa 5eb15fa 59177aa 5eb15fa 59177aa 5eb15fa 59177aa 5eb15fa 59177aa fe49aa3 c99406b d3caf4c fe49aa3 59177aa d3caf4c 59177aa fe49aa3 59177aa fe49aa3 4f228ef 5eb15fa 59177aa 5eb15fa 59177aa d3caf4c 5eb15fa 59177aa 5eb15fa fe49aa3 59177aa c99406b fe49aa3 59177aa d3caf4c 59177aa d3caf4c 59177aa c99406b 59177aa 79f2daf c99406b fe49aa3 59177aa fe49aa3 79f2daf 59177aa 79f2daf d3caf4c 59177aa c99406b 3f26784 c99406b d3caf4c 59177aa 1df6810 c99406b d3caf4c 1df6810 59177aa 6db8a66 d3caf4c 6db8a66 d3caf4c 59177aa fe49aa3 59177aa fe49aa3 d3caf4c 24cd13f 59177aa 5eb15fa 59177aa d3caf4c c99406b cf8b7b0 d3caf4c 59177aa d3caf4c 59177aa d3caf4c c99406b d3caf4c c99406b 59177aa c99406b 59177aa c99406b 59177aa d3caf4c 59177aa fe49aa3 59177aa d3caf4c 59177aa d3caf4c 59177aa d3caf4c 59177aa d3caf4c 59177aa d3caf4c fe49aa3 1df6810 d3caf4c a589da1 59177aa 62d2b15 d3caf4c 8761807 d3caf4c 8761807 62d2b15 d3caf4c 59177aa 62d2b15 59177aa 9a48a94 eb59db6 59177aa 75e05d9 59177aa eb59db6 62d2b15 59177aa 24cd13f 59177aa eb59db6 4f228ef eb59db6 d3caf4c 9a48a94 d3caf4c eb59db6 c1866e9 eb59db6 e41b021 59177aa eb59db6 e41b021 d3caf4c 59177aa eb59db6 59177aa d3caf4c eb59db6 e41b021 59177aa e41b021 d3caf4c eb59db6 d3caf4c eb59db6 d3caf4c eb59db6 24cd13f d3caf4c eb59db6 26be385 eb59db6 26be385 d3caf4c 24cd13f d3caf4c 24cd13f 59177aa 24cd13f d3caf4c 71c328b 24cd13f 71c328b 24cd13f 71c328b 59177aa d3caf4c 4f228ef 59177aa 4f228ef 59177aa 4f228ef 59177aa e41b021 59177aa 1df6810 59177aa d3caf4c 1df6810 d3caf4c |
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 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 |
# ──────────────────────────────── Imports ────────────────────────────────
import os, json, re, logging, requests, markdown, time, io
from datetime import datetime
import streamlit as st
st.set_page_config(layout="wide")
from openai import OpenAI # OpenAI 라이브러리
from gradio_client import Client
import pandas as pd
import PyPDF2 # For handling PDF files
# ──────────────────────────────── Environment Variables / Constants ─────────────────────────
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
BRAVE_KEY = os.getenv("SERPHOUSE_API_KEY", "") # Keep this name
BRAVE_ENDPOINT = "https://api.search.brave.com/res/v1/web/search"
IMAGE_API_URL = "http://211.233.58.201:7896" # 이미지 생성용 API
MAX_TOKENS = 7999
# ──────────────────────────────── Physical Transformation Categories (KR & EN) ─────────────────
physical_transformation_categories = {
"센서 기능": [
"시각 센서/감지", "청각 센서/감지", "촉각 센서/감지", "미각 센서/감지", "후각 센서/감지",
"온도 센서/감지", "습도 센서/감지", "압력 센서/감지", "가속도 센서/감지", "회전 센서/감지",
"근접 센서/감지", "위치 센서/감지", "운동 센서/감지", "가스 센서/감지", "적외선 센서/감지",
"자외선 센서/감지", "방사선 센서/감지", "자기장 센서/감지", "전기장 센서/감지", "화학물질 센서/감지",
"생체신호 센서/감지", "진동 센서/감지", "소음 센서/감지", "빛 세기 센서/감지", "빛 파장 센서/감지",
"기울기 센서/감지", "pH 센서/감지", "전류 센서/감지", "전압 센서/감지", "이미지 센서/감지",
"거리 센서/감지", "깊이 센서/감지", "중력 센서/감지", "속도 센서/감지", "흐름 센서/감지",
"수위 센서/감지", "탁도 센서/감지", "염도 센서/감지", "금속 감지", "압전 센서/감지",
"광전 센서/감지", "열전대 센서/감지", "홀 효과 센서/감지", "초음파 센서/감지", "레이더 센서/감지",
"라이다 센서/감지", "터치 센서/감지", "제스처 센서/감지", "심박 센서/감지", "혈압 센서/감지"
],
"크기와 형태 변화": [
"부피 늘어남/줄어듦", "길이 늘어남/줄어듦", "너비 늘어남/줄어듦", "높이 늘어남/줄어듦",
"밀도 변화", "무게 증가/감소", "모양 변형", "상태 변화", "불균등 변형",
"복잡한 형태 변형", "비틀림/꼬임", "불균일한 확장/축소", "모서리 둥글게/날카롭게",
"깨짐/갈라짐", "여러 조각 나눠짐", "물 저항", "먼지 저항", "찌그러짐/복원",
"접힘/펼쳐짐", "압착/팽창", "늘어남/수축", "구겨짐/평평해짐", "뭉개짐/단단해짐",
"말림/펴짐", "꺾임/구부러짐"
],
"표면 및 외관 변화": [
"색상 변화", "질감 변화", "투명/불투명 변화", "반짝임/무광 변화",
"빛 반사 정도 변화", "무늬 변화", "각도에 따른 색상 변화", "빛에 따른 색상 변화",
"온도에 따른 색상 변화", "홀로그램 효과", "표면 각도별 빛 반사", "표면 모양 변형",
"초미세 표면 구조 변화", "자가 세정 효과", "얼룩/패턴 생성", "흐림/선명함 변화",
"광택/윤기 변화", "색조/채도 변화", "발광/형광", "빛 산란 효과",
"빛 흡수 변화", "반투명 효과", "그림자 효과 변화", "자외선 반응 변화",
"야광 효과"
],
"물질의 상태 변화": [
"고체/액체/기체 전환", "결정화/용해", "산화/부식", "딱딱해짐/부드러워짐",
"특수 상태 전환", "무정형/결정형 전환", "성분 분리", "미세 입자 형성/분해",
"젤 형성/풀어짐", "준안정 상태 변화", "분자 자가 정렬/분해", "상태변화 지연 현상",
"녹음", "굳음", "증발/응축", "승화/증착", "침전/부유", "분산/응집",
"건조/습윤", "팽윤/수축", "동결/해동", "풍화/침식", "충전/방전",
"결합/분리", "발효/부패"
],
"움직임 특성 변화": [
"가속/감속", "일정 속도 유지", "진동/진동 감소", "부딪힘/튕김",
"회전 속도 증가/감소", "회전 방향 변화", "불규칙 움직임", "멈췄다 미끄러지는 현상",
"공진/반공진", "유체 속 저항/양력 변화", "움직임 저항 변화", "복합 진동 움직임",
"특수 유체 속 움직임", "회전-이동 연계 움직임", "관성 정지", "충격 흡수",
"충격 전달", "운동량 보존", "마찰력 변화", "관성 탈출", "불안정 균형",
"동적 안정성", "흔들림 감쇠", "경로 예측성", "회피 움직임"
],
"구조적 변화": [
"부품 추가/제거", "조립/분해", "접기/펴기", "변형/원상복구", "최적 구조 변화",
"자가 재배열", "자연 패턴 형성/소멸", "규칙적 패턴 변화", "모듈식 변형",
"복잡성 증가 구조", "원래 모양 기억 효과", "시간에 따른 형태 변화", "부분 제거",
"부분 교체", "결합", "분리", "분할/통합", "중첩/겹침", "내부 구조 변화",
"외부 구조 변화", "중심축 이동", "균형점 변화", "계층 구조 변화", "지지 구조 변화",
"응력 분산 구조", "충격 흡수 구조", "그리드/매트릭스 구조 변화", "상호 연결성 변화"
],
"공간 이동": [
"앞/뒤 이동", "좌/우 이동", "위/아래 이동", "세로축 회전(고개 끄덕임)",
"가로축 회전(고개 젓기)", "길이축 회전(옆으로 기울임)", "원 운동", "나선형 이동",
"관성에 의한 미끄러짐", "회전축 변화", "불규칙 회전", "흔들림 운동", "포물선 이동",
"무중력 부유", "수면 위 부유", "점프/도약", "슬라이딩", "롤링", "자유 낙하",
"왕복 운동", "탄성 튕김", "관통", "회피 움직임", "지그재그 이동", "스윙 운동"
],
"시간 관련 변화": [
"노화/풍화", "마모/부식", "색 바램/변색", "손상/회복", "수명 주기 변화",
"사용자 상호작용에 따른 적응", "학습 기반 형태 최적화", "시간에 따른 물성 변화",
"집단 기억 효과", "문화적 의미 변화", "지연 반응", "이전 상태 의존 변화",
"점진적 시간 변화", "진화적 변화", "주기적 재생", "계절 변화 적응",
"생체리듬 변화", "생애 주기 단계", "성장/퇴화", "자가 복구/재생",
"자연 순환 적응", "지속성/일시성", "기억 효과", "지연된 작용", "누적 효과"
],
"빛과 시각 효과": [
"발광/소등", "빛 투과/차단", "빛 산란/집중", "색상 스펙트럼 변화", "빛 회절",
"빛 간섭", "홀로그램 생성", "레이저 효과", "빛 편광", "형광/인광",
"자외선/적외선 발광", "광학적 착시", "빛 굴절", "그림자 생성/제거",
"색수차 효과", "무지개 효과", "글로우 효과", "플래시 효과", "조명 패턴",
"빔 효과", "광 필터 효과", "빛의 방향성 변화", "투영 효과", "빛 감지/반응",
"광도 변화"
],
"소리와 진동 효과": [
"소리 발생/소멸", "음 높낮이 변화", "음량 변화", "음색 변화",
"공명/반공명", "음향 진동", "초음파/저음파 발생", "소리 집중/분산",
"음향 반사/흡수", "음향 도플러 효과", "음파 간섭", "음향 공진",
"진동 패턴 변화", "타악 효과", "음향 피드백", "음향 차폐/증폭",
"소리 지향성", "소리 왜곡", "비트 생성", "배음 생성", "주파수 변조",
"음향 충격파", "음향 필터링"
],
"열 관련 변화": [
"온도 상승/하강", "열 팽창/수축", "열 전달/차단", "압력 상승/하강",
"열 변화에 따른 자화", "엔트로피 변화", "열전기 효과", "자기장에 의한 열 변화",
"상태 변화 중 열 저장/방출", "열 스트레스 발생/해소", "급격한 온도 변화 영향",
"복사 냉각/가열", "발열/흡열", "열 분포 변화", "열 반사/흡수",
"냉각 응축", "열 활성화", "열 변색", "열 팽창 계수 변화", "열 안정성 변화",
"내열성/내한성", "자가 발열", "열적 평형/불균형", "열적 변형", "열 분산/집중"
],
"전기 및 자기 변화": [
"자성 생성/소멸", "전하량 증가/감소", "전기장 생성/소멸", "자기장 생성/소멸",
"초전도 상태 전환", "강유전체 특성 변화", "양자 상태 변화", "플라즈마 형성/소멸",
"스핀파 전달", "빛에 의한 전기 발생", "압력에 의한 전기 발생", "자기장 내 전류 변화",
"전기 저항 변화", "전기 전도성 변화", "정전기 발생/방전", "전자기 유도",
"전자기파 방출/흡수", "전기 용량 변화", "자기 이력 현상", "전기적 분극",
"전자 흐름 방향 변화", "전기적 공명", "전기적 차폐/노출", "자기 차폐/노출",
"자기장 정렬"
],
"화학적 변화": [
"표면 코팅 변화", "물질 성분 변화", "화학 반응 변화", "촉매 작용 시작/중단",
"빛에 의한 화학 반응", "전기에 의한 화학 반응", "단분자막 형성", "분자 수준 구조 변화",
"생체 모방 표면 변화", "환경 반응형 물질 변화", "주기적 화학 반응", "산화", "환원",
"고분자화", "물 분해", "화합", "방사선 영향", "산-염기 반응", "중화 반응",
"이온화", "화학적 흡착/탈착", "촉매 효율 변화", "효소 활성 변화", "발색 반응",
"pH 변화", "화학적 평형 이동", "결합 형성/분해", "용해도 변화"
],
"생물학적 변화": [
"성장/위축", "세포 분열/사멸", "생물 발광", "신진대사 변화", "면역 반응",
"호르몬 분비", "신경 반응", "유전적 발현", "적응/진화", "생체리듬 변화",
"재생/치유", "노화/성숙", "생체 모방 변화", "바이오필름 형성", "생물학적 분해",
"효소 활성화/비활성화", "생물학적 신호 전달", "스트레스 반응", "체온 조절", "생물학적 시계 변화",
"세포외 기질 변화", "생체 역학적 반응", "세포 운동성", "세포 극성 변화", "영양 상태 변화"
],
"환경 상호작용": [
"온도 반응", "습도 반응", "기압 반응", "중력 반응", "자기장 반응",
"빛 반응", "소리 반응", "화학 물질 감지", "기계적 자극 감지", "전기 자극 반응",
"방사선 반응", "진동 감지", "pH 반응", "용매 반응", "기체 교환",
"환경 오염 반응", "날씨 반응", "계절 반응", "일주기 반응", "생태계 상호작용",
"공생/경쟁 반응", "포식/피식 관계", "군집 형성", "영역 설정", "이주/정착 패턴"
],
"비즈니스 아이디어": [
"시장 재정의/신규 시장 개척",
"비즈니스 모델 혁신/디지털 전환",
"고객 경험 혁신/서비스 혁신",
"협력 및 파트너십 강화/생태계 구축",
"글로벌 확장/지역화 전략",
"운영 효율성 증대/원가 절감",
"브랜드 리포지셔닝/이미지 전환",
"지속 가능한 성장/사회적 가치 창출",
"데이터 기반 의사결정/AI 도입",
"신기술 융합/혁신 투자"
]
}
physical_transformation_categories_en = {
"Sensor Functions": [
"Visual sensor/detection", "Auditory sensor/detection", "Tactile sensor/detection", "Taste sensor/detection", "Olfactory sensor/detection",
"Temperature sensor/detection", "Humidity sensor/detection", "Pressure sensor/detection", "Acceleration sensor/detection", "Rotational sensor/detection",
"Proximity sensor/detection", "Position sensor/detection", "Motion sensor/detection", "Gas sensor/detection", "Infrared sensor/detection",
"Ultraviolet sensor/detection", "Radiation sensor/detection", "Magnetic sensor/detection", "Electric field sensor/detection", "Chemical sensor/detection",
"Biosignal sensor/detection", "Vibration sensor/detection", "Noise sensor/detection", "Light intensity sensor/detection", "Light wavelength sensor/detection",
"Tilt sensor/detection", "pH sensor/detection", "Current sensor/detection", "Voltage sensor/detection", "Image sensor/detection",
"Distance sensor/detection", "Depth sensor/detection", "Gravity sensor/detection", "Speed sensor/detection", "Flow sensor/detection",
"Water level sensor/detection", "Turbidity sensor/detection", "Salinity sensor/detection", "Metal detection", "Piezoelectric sensor/detection",
"Photovoltaic sensor/detection", "Thermocouple sensor/detection", "Hall effect sensor/detection", "Ultrasonic sensor/detection", "Radar sensor/detection",
"Lidar sensor/detection", "Touch sensor/detection", "Gesture sensor/detection", "Heart rate sensor/detection", "Blood pressure sensor/detection"
],
"Size and Shape Change": [
"Volume increase/decrease", "Length increase/decrease", "Width increase/decrease", "Height increase/decrease",
"Density change", "Weight increase/decrease", "Shape deformation", "State change", "Uneven deformation",
"Complex shape deformation", "Twisting/entwining", "Non-uniform expansion/contraction", "Rounded/sharpened edges",
"Cracking/splitting", "Fragmentation", "Water resistance", "Dust resistance", "Denting/recovery",
"Folding/unfolding", "Compression/expansion", "Stretching/contraction", "Wrinkling/flattening", "Crushing/hardening",
"Rolling/unrolling", "Bending/curving"
],
"Surface and Appearance Change": [
"Color change", "Texture change", "Transparency change", "Glossy/matte change",
"Light reflection variation", "Pattern change", "Angle-dependent color change", "Light-induced color change",
"Temperature-dependent color change", "Holographic effect", "Angle-specific light reflection", "Surface shape alteration",
"Nano-scale surface structure change", "Self-cleaning effect", "Stain/pattern formation", "Blurriness/clarity change",
"Luster/shine change", "Hue/saturation change", "Luminescence/fluorescence", "Light scattering effect",
"Light absorption change", "Translucency effect", "Shadow effect change", "UV response change",
"Glow effect"
],
"Material State Change": [
"Solid/liquid/gas transition", "Crystallization/dissolution", "Oxidation/corrosion", "Hardening/softening",
"Special state transition", "Amorphous/crystalline transition", "Component separation", "Particle formation/disintegration",
"Gel formation/dissolution", "Metastable state change", "Molecular self-assembly/disintegration", "Delayed state change",
"Melting", "Solidification", "Evaporation/condensation", "Sublimation/deposition", "Precipitation/suspension", "Dispersion/aggregation",
"Drying/moistening", "Swelling/shrinkage", "Freezing/thawing", "Weathering/erosion", "Charging/discharging",
"Bonding/separation", "Fermentation/decay"
],
"Movement Characteristics Change": [
"Acceleration/deceleration", "Maintaining constant speed", "Vibration/vibration reduction", "Collision/bouncing",
"Increase/decrease in rotational speed", "Change in rotational direction", "Irregular movement", "Stop-and-slide phenomenon",
"Resonance/anti-resonance", "Resistance/lift change in fluid", "Change in movement resistance", "Complex vibrational movement",
"Movement in special fluid", "Rotational-translational movement", "Inertial stoppage", "Shock absorption",
"Shock transfer", "Conservation of momentum", "Friction change", "Overcoming inertia", "Unstable equilibrium",
"Dynamic stability", "Damping of oscillation", "Path predictability", "Evasive movement"
],
"Structural Change": [
"Addition/removal of components", "Assembly/disassembly", "Folding/unfolding", "Deformation/recovery", "Optimal structural change",
"Self-rearrangement", "Natural pattern formation/disappearance", "Regular pattern change", "Modular transformation",
"Increased structural complexity", "Memory of original shape effect", "Shape change over time", "Partial removal",
"Partial replacement", "Bonding", "Separation", "Division/integration", "Overlaying", "Internal structure change",
"External structure change", "Shift of center axis", "Balance point change", "Hierarchical structure change", "Support structure change",
"Stress distribution structure", "Shock absorption structure", "Grid/matrix structure change", "Interconnectivity change"
],
"Spatial Movement": [
"Forward/backward movement", "Left/right movement", "Up/down movement", "Vertical axis rotation (nodding)",
"Horizontal axis rotation (shaking head)", "Longitudinal axis rotation (tilting sideways)", "Circular motion", "Spiral movement",
"Slipping due to inertia", "Change of rotation axis", "Irregular rotation", "Shaking movement", "Parabolic motion",
"Zero-gravity floating", "Floating on water surface", "Jump/leap", "Sliding", "Rolling", "Free fall",
"Reciprocating motion", "Elastic bouncing", "Penetration", "Evasive movement", "Zigzag movement", "Swinging movement"
],
"Time-Related Change": [
"Aging/weathering", "Wear/corrosion", "Fading/discoloration", "Damage/recovery", "Lifecycle change",
"Adaptation through user interaction", "Learning-based shape optimization", "Property change over time",
"Collective memory effect", "Cultural significance change", "Delayed response", "History-dependent change",
"Gradual time change", "Evolutionary change", "Periodic regeneration", "Seasonal adaptation",
"Circadian rhythm change", "Lifecycle stage", "Growth/decline", "Self-repair/regeneration",
"Natural cycle adaptation", "Persistence/transience", "Memory effect", "Delayed effect", "Cumulative effect"
],
"Light and Visual Effects": [
"Illumination/shutdown", "Light transmission/blocking", "Light scattering/concentration", "Color spectrum change", "Light diffraction",
"Light interference", "Hologram creation", "Laser effect", "Light polarization", "Fluorescence/phosphorescence",
"UV/IR emission", "Optical illusion", "Light refraction", "Shadow creation/removal",
"Chromatic aberration", "Rainbow effect", "Glow effect", "Flash effect", "Lighting pattern",
"Beam effect", "Light filter effect", "Change in light direction", "Projection effect", "Light detection/response",
"Luminance change"
],
"Sound and Vibration Effects": [
"Sound generation/cessation", "Pitch change", "Volume change", "Timbre change",
"Resonance/antiresonance", "Acoustic vibration", "Ultrasonic/infrasonic emission", "Sound concentration/distribution",
"Sound reflection/absorption", "Acoustic Doppler effect", "Sound wave interference", "Acoustic resonance",
"Vibration pattern change", "Percussive effect", "Audio feedback", "Sound shielding/amplification",
"Directional sound", "Sound distortion", "Beat generation", "Harmonics generation", "Frequency modulation",
"Acoustic shockwave", "Sound filtering"
],
"Thermal Changes": [
"Temperature rise/fall", "Thermal expansion/contraction", "Heat transfer/blocking", "Pressure increase/decrease",
"Magnetization due to heat change", "Entropy change", "Thermoelectric effect", "Magnetic-induced thermal change",
"Heat storage/release during phase change", "Thermal stress buildup/release", "Impact of rapid temperature change",
"Radiative cooling/heating", "Exothermic/endothermic", "Heat distribution change", "Heat reflection/absorption",
"Cooling condensation", "Thermal activation", "Thermal discoloration", "Coefficient of thermal expansion change", "Thermal stability change",
"Heat resistance/cold resistance", "Self-heating", "Thermal equilibrium/imbalance", "Thermal deformation", "Heat dispersion/concentration"
],
"Electrical and Magnetic Changes": [
"Magnetism creation/cessation", "Charge increase/decrease", "Electric field creation/cessation", "Magnetic field creation/cessation",
"Superconducting transition", "Ferroelectric property change", "Quantum state change", "Plasma formation/cessation",
"Spin wave transmission", "Electricity generation by light", "Electricity generation by pressure", "Current change in magnetic field",
"Electrical resistance change", "Electrical conductivity change", "Static electricity generation/discharge", "Electromagnetic induction",
"Electromagnetic wave emission/absorption", "Capacitance change", "Magnetic hysteresis", "Electrical polarization",
"Electron flow direction change", "Electrical resonance", "Electrical shielding/exposure", "Magnetic shielding/exposure",
"Magnetic field alignment"
],
"Chemical Change": [
"Surface coating change", "Material composition change", "Chemical reaction change", "Catalytic action start/stop",
"Light-induced chemical reaction", "Electricity-induced chemical reaction", "Monolayer formation", "Molecular-level structural change",
"Biomimetic surface change", "Environmentally responsive material change", "Periodic chemical reaction", "Oxidation", "Reduction",
"Polymerization", "Water splitting", "Compound formation", "Radiation effects", "Acid-base reaction", "Neutralization reaction",
"Ionization", "Chemical adsorption/desorption", "Catalytic efficiency change", "Enzyme activity change", "Colorimetric reaction",
"pH change", "Chemical equilibrium shift", "Bond formation/breakage", "Solubility change"
],
"Biological Change": [
"Growth/shrinkage", "Cell division/death", "Bioluminescence", "Metabolic change", "Immune response",
"Hormone secretion", "Neural response", "Genetic expression", "Adaptation/evolution", "Circadian rhythm change",
"Regeneration/healing", "Aging/maturation", "Biomimetic change", "Biofilm formation", "Biological degradation",
"Enzyme activation/inactivation", "Biological signaling", "Stress response", "Thermoregulation", "Biological clock change",
"Extracellular matrix change", "Biomechanical response", "Cell motility", "Cell polarity change", "Nutritional status change"
],
"Environmental Interaction": [
"Temperature response", "Humidity response", "Pressure response", "Gravity response", "Magnetic field response",
"Light response", "Sound response", "Chemical detection", "Mechanical stimulus detection", "Electrical stimulus response",
"Radiation response", "Vibration detection", "pH response", "Solvent response", "Gas exchange",
"Pollution response", "Weather response", "Seasonal response", "Circadian response", "Ecosystem interaction",
"Symbiotic/competitive interaction", "Predator/prey relationship", "Swarm formation", "Territorial behavior", "Migration/settlement pattern"
],
"Business Ideas": [
"Market redefinition / New market creation",
"Business model innovation / Digital transformation",
"Customer experience innovation / Service innovation",
"Strengthened collaboration and partnerships / Ecosystem building",
"Global expansion / Localization strategy",
"Increased operational efficiency / Cost reduction",
"Brand repositioning / Image transformation",
"Sustainable growth / Social value creation",
"Data-driven decision making / AI adoption",
"Convergence of new technologies / Innovative investments"
]
}
# ──────────────────────────────── Logging ────────────────────────────────
logging.basicConfig(level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s")
# ──────────────────────────────── OpenAI Client ──────────────────────────
@st.cache_resource
def get_openai_client():
"""Create an OpenAI client with timeout and retry settings."""
if not OPENAI_API_KEY:
raise RuntimeError("⚠️ OPENAI_API_KEY 환경 변수가 설정되지 않았습니다.")
return OpenAI(
api_key=OPENAI_API_KEY,
timeout=60.0, # 타임아웃 60초로 설정
max_retries=3 # 재시도 횟수 3회로 설정
)
# ──────────────────────────────── New System Prompt for Idea Generation ─────────────────────
# ───────────────── System Prompt (REPORT STYLE) ─────────────────
def get_idea_system_prompt(selected_category: str | None = None) -> str:
"""
Return an enhanced system prompt that forces:
▸ Report-style output with tables
▸ Clear focus on NEED ▸ VALUE ▸ PROBLEM SOLVED ▸ IMPLEMENTATION SNAPSHOT
▸ Three idea modes: Similarity-based, Contrarian, Random
▸ If `selected_category` is given, all ideas must chiefly reference
sub-items inside that category.
"""
cat_clause = (f"\n**Category Focus**: Concentrate on the Korean list "
f"under “{selected_category}”. You *must* anchor every idea "
"to 2-3 sub-items from this category and reference them by name.\n")
prompt = f"""
반드시 한글(한국어)로 답변하라. You are an elite innovation consultant. Your deliverable is a concise **report** in Markdown.
### OUTPUT SPECIFICATION
Produce **exactly three ideas** (Similarity-Based, Contrarian, Random) using these sections **for *each* idea**:
| 항목 | 내용 |
|---|---|
| **Idea Title** | 8-12 Korean characters + 영문 괄호별칭 |
| **Need / Pain-Point** | 어떤 문제·기회 때문에 필요한가? (1-2 문장) |
| **Core Concept** | 아이디어 개요 (2-3 문단) |
| **Key Category Links** | 사용한 변환 카테고리/하위항목(3개 이하) |
| **Value Proposition** | 기대 효과·가치 (불릿 3개) |
| **Potential Obstacles** | 주요 리스크·제약 (불릿 2-3개) |
| **Image Prompt** | 영문 1줄로 시각화를 위한 프롬프트 |
- 포함된 표는 마크다운 그대로 출력.
- 세 아이디어를 “## Idea 1”, “## Idea 2”, “## Idea 3” 헤딩으로 순서화.
- 전문용어 최소화, 간결하지만 설득력 있게.
### IDEA MODES
1. **Similarity-Based Augmentation** – 기존 주제와 가장 가깝게 확장.
2. **Contrarian / Inverse** – 주제의 전제를 뒤집어 새로운 시각 제시.
3. **Random Spark** – 무작위 하위항목(카테고리 불문)을 결합한 의외의 통찰.
{cat_clause if selected_category else ""}
Always think step-by-step but **show only the final report**.
"""
return prompt.strip()
# ──────────────────────────────── Brave Search API ────────────────────────
@st.cache_data(ttl=3600)
def brave_search(query: str, count: int = 20):
"""
Call the Brave Web Search API → list[dict]
Returns fields: index, title, link, snippet, displayed_link
"""
if not BRAVE_KEY:
raise RuntimeError("⚠️ SERPHOUSE_API_KEY (Brave API Key) 환경 변수가 비어있습니다.")
headers = {
"Accept": "application/json",
"Accept-Encoding": "gzip",
"X-Subscription-Token": BRAVE_KEY
}
params = {"q": query, "count": str(count)}
for attempt in range(3):
try:
r = requests.get(BRAVE_ENDPOINT, headers=headers, params=params, timeout=15)
r.raise_for_status()
data = r.json()
logging.info(f"Brave search result data structure: {list(data.keys())}")
raw = data.get("web", {}).get("results") or data.get("results", [])
if not raw:
logging.warning(f"No Brave search results found. Response: {data}")
raise ValueError("No search results found.")
arts = []
for i, res in enumerate(raw[:count], 1):
url = res.get("url", res.get("link", ""))
host = re.sub(r"https?://(www\.)?", "", url).split("/")[0]
arts.append({
"index": i,
"title": res.get("title", "No title"),
"link": url,
"snippet": res.get("description", res.get("text", "No snippet")),
"displayed_link": host
})
logging.info(f"Brave search success: {len(arts)} results")
return arts
except Exception as e:
logging.error(f"Brave search failure (attempt {attempt+1}/3): {e}")
if attempt < 2:
time.sleep(2)
return []
def mock_results(query: str) -> str:
"""Fallback if search API fails"""
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return (f"# Fallback Search Content (Generated: {ts})\n\n"
f"The web search API request failed. Please generate the ideas based on general knowledge about '{query}'.\n\n"
f"You may consider aspects such as:\n\n"
f"- Basic definition or concept of {query}\n"
f"- Commonly known facts or challenges\n"
f"- Potential categories from the transformation list\n\n"
f"Note: This is fallback guidance, not real-time data.\n\n")
def do_web_search(query: str) -> str:
"""Perform web search and format the results."""
try:
arts = brave_search(query, 20)
if not arts:
logging.warning("No search results, using fallback content")
return mock_results(query)
hdr = "# Web Search Results\nUse the information below to inspire or validate your ideas.\n\n"
body = "\n".join(
f"### Result {a['index']}: {a['title']}\n\n{a['snippet']}\n\n"
f"**Source**: [{a['displayed_link']}]({a['link']})\n\n---\n"
for a in arts
)
return hdr + body
except Exception as e:
logging.error(f"Web search process failed: {str(e)}")
return mock_results(query)
# ──────────────────────────────── File Upload Handling ─────────────────────
def process_text_file(file):
"""Handle text file"""
try:
content = file.read()
file.seek(0)
text = content.decode('utf-8', errors='ignore')
if len(text) > 10000:
text = text[:9700] + "...(truncated)..."
result = f"## Text File: {file.name}\n\n"
result += text
return result
except Exception as e:
logging.error(f"Error processing text file: {str(e)}")
return f"Error processing text file: {str(e)}"
def process_csv_file(file):
"""Handle CSV file"""
try:
content = file.read()
file.seek(0)
df = pd.read_csv(io.BytesIO(content))
result = f"## CSV File: {file.name}\n\n"
result += f"- Rows: {len(df)}\n"
result += f"- Columns: {len(df.columns)}\n"
result += f"- Column Names: {', '.join(df.columns.tolist())}\n\n"
result += "### Data Preview\n\n"
preview_df = df.head(10)
try:
markdown_table = preview_df.to_markdown(index=False)
if markdown_table:
result += markdown_table + "\n\n"
else:
result += "Unable to display CSV data.\n\n"
except Exception as e:
logging.error(f"Markdown table conversion error: {e}")
result += "Displaying data as text:\n\n"
result += str(preview_df) + "\n\n"
num_cols = df.select_dtypes(include=['number']).columns
if len(num_cols) > 0:
result += "### Basic Statistical Information\n\n"
try:
stats_df = df[num_cols].describe().round(2)
stats_markdown = stats_df.to_markdown()
if stats_markdown:
result += stats_markdown + "\n\n"
else:
result += "Unable to display statistical information.\n\n"
except Exception as e:
logging.error(f"Statistical info conversion error: {e}")
result += "Unable to generate statistical information.\n\n"
return result
except Exception as e:
logging.error(f"CSV file processing error: {str(e)}")
return f"Error processing CSV file: {str(e)}"
def process_pdf_file(file):
"""Handle PDF file"""
try:
file_bytes = file.read()
file.seek(0)
pdf_file = io.BytesIO(file_bytes)
reader = PyPDF2.PdfReader(pdf_file, strict=False)
result = f"## PDF File: {file.name}\n\n"
result += f"- Total pages: {len(reader.pages)}\n\n"
max_pages = min(5, len(reader.pages))
all_text = ""
for i in range(max_pages):
try:
page = reader.pages[i]
page_text = page.extract_text()
current_page_text = f"### Page {i+1}\n\n"
if page_text and len(page_text.strip()) > 0:
if len(page_text) > 1500:
current_page_text += page_text[:1500] + "...(truncated)...\n\n"
else:
current_page_text += page_text + "\n\n"
else:
current_page_text += "(No text could be extracted)\n\n"
all_text += current_page_text
if len(all_text) > 8000:
all_text += "...(truncating remaining pages; PDF is too large)...\n\n"
break
except Exception as page_err:
logging.error(f"Error processing PDF page {i+1}: {str(page_err)}")
all_text += f"### Page {i+1}\n\n(Error extracting content: {str(page_err)})\n\n"
if len(reader.pages) > max_pages:
all_text += f"\nNote: Only the first {max_pages} pages are shown out of {len(reader.pages)} total.\n\n"
result += "### PDF Content\n\n" + all_text
return result
except Exception as e:
logging.error(f"PDF file processing error: {str(e)}")
return f"## PDF File: {file.name}\n\nError occurred: {str(e)}\n\nThis PDF file cannot be processed."
def process_uploaded_files(files):
"""Combine the contents of all uploaded files into one string."""
if not files:
return None
result = "# Uploaded File Contents\n\n"
result += "Below is the content from the files provided by the user. Integrate this data as needed for generating ideas.\n\n"
for file in files:
try:
ext = file.name.split('.')[-1].lower()
if ext == 'txt':
result += process_text_file(file) + "\n\n---\n\n"
elif ext == 'csv':
result += process_csv_file(file) + "\n\n---\n\n"
elif ext == 'pdf':
result += process_pdf_file(file) + "\n\n---\n\n"
else:
result += f"### Unsupported File: {file.name}\n\n---\n\n"
except Exception as e:
logging.error(f"File processing error {file.name}: {e}")
result += f"### File processing error: {file.name}\n\nError: {e}\n\n---\n\n"
return result
# ──────────────────────────────── Image & Utility ─────────────────────────
def generate_image(prompt, w=768, h=768, g=3.5, steps=30, seed=3):
"""Image generation function."""
if not prompt:
return None, "Insufficient prompt"
try:
res = Client(IMAGE_API_URL).predict(
prompt=prompt, width=w, height=h, guidance=g,
inference_steps=steps, seed=seed,
do_img2img=False, init_image=None,
image2image_strength=0.8, resize_img=True,
api_name="/generate_image"
)
return res[0], f"Seed: {res[1]}"
except Exception as e:
logging.error(e)
return None, str(e)
def md_to_html(md: str, title="Idea Output"):
"""Convert Markdown to HTML."""
return f"<!DOCTYPE html><html><head><title>{title}</title><meta charset='utf-8'></head><body>{markdown.markdown(md)}</body></html>"
def keywords(text: str, top=5):
"""Simple keyword extraction (for web search)."""
cleaned = re.sub(r"[^가-힣a-zA-Z0-9\s]", "", text)
return " ".join(cleaned.split()[:top])
# ──────────────────────────────── Streamlit UI ────────────────────────────
def idea_generator_app():
st.title("Creative Idea Generator")
# Set default session state
if "ai_model" not in st.session_state:
st.session_state.ai_model = "gpt-4.1-mini"
if "messages" not in st.session_state:
st.session_state.messages = []
if "auto_save" not in st.session_state:
st.session_state.auto_save = True
if "generate_image" not in st.session_state:
st.session_state.generate_image = True # 기본값: True
if "web_search_enabled" not in st.session_state:
st.session_state.web_search_enabled = True
# Sidebar UI
sb = st.sidebar
sb.title("Idea Generator Settings")
sb.toggle("Auto Save", key="auto_save")
sb.toggle("Auto Image Generation", key="generate_image")
web_search_enabled = sb.toggle("Use Web Search", value=st.session_state.web_search_enabled)
st.session_state.web_search_enabled = web_search_enabled
if web_search_enabled:
sb.info("✅ Web search results will be integrated.")
# 예시 주제들 (원래 예시 블로그 토픽 -> 이제는 예시 아이디어 주제로 전환)
example_topics = {
"example1": "AI로 인한 비즈니스 모델 변화",
"example2": "스마트 소재를 활용한 친환경 건축",
"example3": "미래형 교육 서비스 구상"
}
sb.subheader("Category Focus (Optional)")
category_keys = ["(None)"] + list(physical_transformation_categories.keys())
sb.selectbox(
"Generate ideas mainly using this category",
options=category_keys,
key="category_focus",
index=0 # 기본값 "(None)"
)
sb.subheader("Example Prompts")
c1, c2, c3 = sb.columns(3)
if c1.button("AI & 비즈니스", key="ex1"):
process_example(example_topics["example1"])
if c2.button("스마트 소재 건축", key="ex2"):
process_example(example_topics["example2"])
if c3.button("미래형 교육", key="ex3"):
process_example(example_topics["example3"])
# Download the latest ideas
latest_ideas = next(
(m["content"] for m in reversed(st.session_state.messages)
if m["role"] == "assistant" and m["content"].strip()),
None
)
if latest_ideas:
title_match = re.search(r"# (.*?)(\n|$)", latest_ideas)
title = title_match.group(1).strip() if title_match else "ideas"
sb.subheader("Download Latest Ideas")
d1, d2 = sb.columns(2)
d1.download_button("Download as Markdown", latest_ideas,
file_name=f"{title}.md", mime="text/markdown")
d2.download_button("Download as HTML", md_to_html(latest_ideas, title),
file_name=f"{title}.html", mime="text/html")
# JSON conversation record upload
up = sb.file_uploader("Load Conversation History (.json)", type=["json"], key="json_uploader")
if up:
try:
st.session_state.messages = json.load(up)
sb.success("Conversation history loaded successfully")
except Exception as e:
sb.error(f"Failed to load: {e}")
# JSON conversation record download
if sb.button("Download Conversation as JSON"):
sb.download_button(
"Save JSON",
data=json.dumps(st.session_state.messages, ensure_ascii=False, indent=2),
file_name="chat_history.json",
mime="application/json"
)
# File Upload
st.subheader("File Upload (Optional)")
uploaded_files = st.file_uploader(
"Upload files to reference in the idea generation (txt, csv, pdf)",
type=["txt", "csv", "pdf"],
accept_multiple_files=True,
key="file_uploader"
)
if uploaded_files:
file_count = len(uploaded_files)
st.success(f"{file_count} files uploaded.")
with st.expander("Preview Uploaded Files", expanded=False):
for idx, file in enumerate(uploaded_files):
st.write(f"**File Name:** {file.name}")
ext = file.name.split('.')[-1].lower()
if ext == 'txt':
preview = file.read(1000).decode('utf-8', errors='ignore')
file.seek(0)
st.text_area(
f"Preview of {file.name}",
preview + ("..." if len(preview) >= 1000 else ""),
height=150
)
elif ext == 'csv':
try:
df = pd.read_csv(file)
file.seek(0)
st.write("CSV Preview (up to 5 rows)")
st.dataframe(df.head(5))
except Exception as e:
st.error(f"CSV preview failed: {e}")
elif ext == 'pdf':
try:
file_bytes = file.read()
file.seek(0)
pdf_file = io.BytesIO(file_bytes)
reader = PyPDF2.PdfReader(pdf_file, strict=False)
pc = len(reader.pages)
st.write(f"PDF File: {pc} pages")
if pc > 0:
try:
page_text = reader.pages[0].extract_text()
preview = page_text[:500] if page_text else "(No text)"
st.text_area("Preview of the first page", preview + "...", height=150)
except:
st.warning("Failed to extract text from the first page")
except Exception as e:
st.error(f"PDF preview failed: {e}")
if idx < file_count - 1:
st.divider()
# Display existing messages in chat
for m in st.session_state.messages:
with st.chat_message(m["role"]):
st.markdown(m["content"])
if "image" in m:
st.image(m["image"], caption=m.get("image_caption", ""))
# User input for idea generation
prompt = st.chat_input("Enter a topic or concept to generate 3 new ideas.")
if prompt:
process_input(prompt, uploaded_files)
# Sidebar footer
sb.markdown("---")
sb.markdown("Created by [Ginigen.com](https://ginigen.com) | [YouTube](https://www.youtube.com/@ginipickaistudio)")
def process_example(topic):
"""Handle example prompts."""
process_input(topic, [])
def process_input(prompt: str, uploaded_files):
# Add user's message
if not any(m["role"] == "user" and m["content"] == prompt
for m in st.session_state.messages):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
placeholder = st.empty()
message_placeholder = st.empty()
full_response = ""
use_web_search = st.session_state.web_search_enabled
has_uploaded = bool(uploaded_files)
try:
status = st.status("Preparing to generate ideas…")
status.update(label="Initializing model…")
client = get_openai_client()
# ── ① 시스템 프롬프트 ──────────────────────────────
selected_cat = st.session_state.get("category_focus", "(None)")
if selected_cat == "(None)":
selected_cat = None
sys_prompt = get_idea_system_prompt(selected_category=selected_cat)
# ── ② (선택) 웹 검색 & 파일내용 ───────────────────
search_content = None
if use_web_search:
status.update(label="Searching the web…")
with st.spinner("Searching…"):
search_content = do_web_search(keywords(prompt, top=5))
file_content = None
if has_uploaded:
status.update(label="Reading uploaded files…")
with st.spinner("Processing files…"):
file_content = process_uploaded_files(uploaded_files)
# ── ③ 대화 메시지 구성 ─────────────────────────────
user_content = prompt
if search_content:
user_content += "\n\n" + search_content
if file_content:
user_content += "\n\n" + file_content
api_messages = [
{"role": "system", "content": sys_prompt},
{"role": "user", "content": user_content},
]
# ── ④ OpenAI 스트리밍 호출 ────────────────────────
status.update(label="Generating ideas…")
stream = client.chat.completions.create(
model = "gpt-4.1-mini",
messages = api_messages,
temperature = 1,
max_tokens = MAX_TOKENS,
top_p = 1,
stream = True
)
for chunk in stream:
if (chunk.choices
and chunk.choices[0].delta.content is not None):
full_response += chunk.choices[0].delta.content
message_placeholder.markdown(full_response + "▌")
message_placeholder.markdown(full_response)
status.update(label="Ideas created!", state="complete")
# ── ⑤ 이미지 생성 ────────────────────────────────
if st.session_state.generate_image and full_response:
idea_sections = re.split(r"(## Idea \d+:)", full_response)
pairs = [(idea_sections[i].strip(),
idea_sections[i+1].strip() if i+1 < len(idea_sections) else "")
for i in range(1, len(idea_sections), 2)]
for idx, (title, text_block) in enumerate(pairs, start=1):
# 표 형태: | **Image Prompt** | prompt |
table_match = re.search(
r"\|\s*\*\*Image\s+Prompt\*\*\s*\|\s*([^\n\|]+)",
text_block, flags=re.IGNORECASE)
# 백업 형태: Image Prompt: …
if not table_match:
table_match = re.search(
r"(?i)Image\s+Prompt\s*[:|-]\s*([^\n]+)", text_block)
if not table_match:
continue
raw_prompt = re.sub(r"[\r\n\|`'\"\\]", " ",
table_match.group(1).strip())
with st.spinner(f"Generating image for {title}…"):
img, cap = generate_image(raw_prompt)
if img:
st.image(img, caption=f"{title} – {cap}")
st.session_state.messages.append({
"role": "assistant",
"content": "",
"image": img,
"image_caption": f"{title} – {cap}"
})
# ── ⑥ 결과 저장 & 다운로드 ─────────────────────────
st.session_state.messages.append(
{"role": "assistant", "content": full_response})
st.subheader("Download This Output")
c1, c2 = st.columns(2)
c1.download_button("Markdown", full_response,
file_name=f"{prompt[:30]}.md",
mime="text/markdown")
c2.download_button("HTML",
md_to_html(full_response, prompt[:30]),
file_name=f"{prompt[:30]}.html",
mime="text/html")
# ── ⑦ 자동 저장 ─────────────────────────────────
if st.session_state.auto_save:
fn = f"chat_history_auto_{datetime.now():%Y%m%d_%H%M%S}.json"
with open(fn, "w", encoding="utf-8") as fp:
json.dump(st.session_state.messages, fp,
ensure_ascii=False, indent=2)
except Exception as e:
err = str(e)
placeholder.error(f"Error: {err}")
logging.error(err)
st.session_state.messages.append(
{"role": "assistant",
"content": f"⚠️ 작업 중 오류가 발생했습니다: {err}"})
# 3개 이미지 생성 프로세스를 마친 후 최종 텍스트를 저장
st.session_state.messages.append({"role": "assistant", "content": full_response})
answer_entry_saved = True
if not answer_entry_saved and full_response:
# 이미지 생성이 비활성화거나 실패했을 경우 텍스트만 저장
st.session_state.messages.append({"role": "assistant", "content": full_response})
# Download buttons
if full_response:
st.subheader("Download This Output")
c1, c2 = st.columns(2)
c1.download_button(
"Markdown",
data=full_response,
file_name=f"{prompt[:30]}.md",
mime="text/markdown"
)
c2.download_button(
"HTML",
data=md_to_html(full_response, prompt[:30]),
file_name=f"{prompt[:30]}.html",
mime="text/html"
)
# Auto-save
if st.session_state.auto_save and st.session_state.messages:
try:
fn = f"chat_history_auto_{datetime.now():%Y%m%d_%H%M%S}.json"
with open(fn, "w", encoding="utf-8") as fp:
json.dump(st.session_state.messages, fp, ensure_ascii=False, indent=2)
except Exception as e:
logging.error(f"Auto-save failed: {e}")
except Exception as e:
error_message = str(e)
placeholder.error(f"An error occurred: {error_message}")
logging.error(f"Process input error: {error_message}")
ans = f"An error occurred while processing your request: {error_message}"
st.session_state.messages.append({"role": "assistant", "content": ans})
# ──────────────────────────────── main ────────────────────────────────────
def main():
idea_generator_app()
if __name__ == "__main__":
main()
|