Spaces:
Running
Running
# cycles_chat_app.py | |
import os, math, numpy as np, matplotlib.pyplot as plt, gradio as gr | |
import openai | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
# 0. OpenAI key | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
if "OPENAI_API_KEY" not in os.environ: | |
os.environ["OPENAI_API_KEY"] = input("๐ Enter your OpenAI API key: ").strip() | |
openai.api_key = os.environ["OPENAI_API_KEY"] | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
# 1. Cycle-chart utilities | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
CYCLES = { | |
"Tech Cycle (50 yr)": 50, | |
"Finance Cycle (80 yr)": 80, | |
"Hegemony Cycle (250 yr)": 250, | |
} | |
CENTER = 2025 # reference year | |
def make_cycle_points(period, start, end): | |
n_min = math.floor((start - CENTER) / period) | |
n_max = math.ceil((end - CENTER) / period) | |
return [CENTER + n * period for n in range(n_min, n_max + 1)] | |
def build_chart_and_summary(start, end): | |
# --------- build figure (tower style) ---------- | |
fig, ax = plt.subplots(figsize=(7, 5)) | |
align_years, summaries = None, [] | |
for idx, (name, period) in enumerate(CYCLES.items()): | |
years = make_cycle_points(period, start, end) | |
ax.scatter([idx] * len(years), years, s=60) | |
for y in years: | |
ax.text(idx, y + 5, str(y), ha="center", va="bottom", fontsize=7) | |
summaries.append(f"{name.replace(' ', ' ')}: {years}") | |
align_years = set(years) if align_years is None else align_years & set(years) | |
if align_years: | |
for y in sorted(align_years): | |
ax.axhline(y, color="black", linestyle="--", linewidth=1) | |
ax.text(-0.4, y + 8, f"Alignment โ {y}", fontsize=9, fontweight="bold") | |
ax.set_xticks(range(len(CYCLES)), CYCLES.keys(), rotation=15) | |
ax.set_ylabel("Year") | |
ax.set_xlabel("Cycle") | |
ax.set_title("Cycle Events and Alignment") | |
ax.set_ylim(start - 10, end + 10) | |
ax.invert_yaxis() # older years at bottom, newer at top | |
ax.grid(axis="y", alpha=0.3) | |
# --------- build textual summary ---------- | |
align_txt = ", ".join(map(str, sorted(align_years))) if align_years else "None" | |
summary = ( | |
f"Range: {start}-{end}\n" | |
+ "\n".join(summaries) | |
+ f"\nAlignment years: {align_txt}" | |
) | |
return fig, summary | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
# 2. GPT chat | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
BASE_PROMPT = ( | |
"You are a concise, accurate assistant who answers in Korean. " | |
"If the chart summary is provided, take it into account." | |
) | |
def chat_with_gpt(history, user_message, chart_summary): | |
messages = [{"role": "system", "content": BASE_PROMPT}] | |
if chart_summary and chart_summary != "No chart yet.": | |
messages.append({"role": "system", "content": f"[Chart summary]\n{chart_summary}"}) | |
for u, a in history: | |
messages.extend([{"role": "user", "content": u}, | |
{"role": "assistant", "content": a}]) | |
messages.append({"role": "user", "content": user_message}) | |
response = openai.chat.completions.create( | |
model="gpt-3.5-turbo", | |
messages=messages, | |
max_tokens=600, | |
temperature=0.7, | |
) | |
return response.choices[0].message.content.strip() | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
# 3. Gradio UI | |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ | |
with gr.Blocks(theme=gr.themes.Soft()) as demo: | |
gr.Markdown("## ๐ Three-Cycle Timeline & ๐ฌ GPT Chat") | |
chart_summary_state = gr.State(value="No chart yet.") | |
with gr.Tabs(): | |
# ---------- Tab 1: Chart ---------- | |
with gr.TabItem("Timeline Chart"): | |
start_year = gr.Number(label="Start Year", value=1500) | |
end_year = gr.Number(label="End Year", value=2500) | |
fig0, summary0 = build_chart_and_summary(1500, 2500) | |
plot_out = gr.Plot(value=fig0) | |
def update_chart(s, e): | |
fig, summ = build_chart_and_summary(int(s), int(e)) | |
return fig, summ | |
start_year.change(update_chart, [start_year, end_year], | |
[plot_out, chart_summary_state]) | |
end_year.change(update_chart, [start_year, end_year], | |
[plot_out, chart_summary_state]) | |
# ---------- Tab 2: GPT Chat ---------- | |
with gr.TabItem("GPT Chat"): | |
chatbot = gr.Chatbot(label="Assistant") | |
user_in = gr.Textbox(placeholder="๋ฉ์์ง๋ฅผ ์ ๋ ฅํ์ธ์...", lines=3) | |
send_btn = gr.Button("Send", variant="primary") | |
def respond(chat_history, user_msg, chart_summary): | |
assistant_msg = chat_with_gpt(chat_history, user_msg, chart_summary) | |
chat_history.append((user_msg, assistant_msg)) | |
return chat_history, gr.Textbox(value="", interactive=True) | |
send_btn.click( | |
respond, | |
inputs=[chatbot, user_in, chart_summary_state], | |
outputs=[chatbot, user_in], | |
) | |
user_in.submit( | |
respond, | |
inputs=[chatbot, user_in, chart_summary_state], | |
outputs=[chatbot, user_in], | |
) | |
if __name__ == "__main__": | |
demo.launch() | |