import os import re import random from http import HTTPStatus from typing import Dict, List, Optional, Tuple import base64 import anthropic from functools import partial import gradio as gr import modelscope_studio.components.base as ms import modelscope_studio.components.legacy as legacy import modelscope_studio.components.antd as antd from config import DEMO_LIST, SystemPrompt def get_image_base64(image_path): with open(image_path, "rb") as image_file: encoded_string = base64.b64encode(image_file.read()).decode() return encoded_string YOUR_API_TOKEN = os.getenv('ANTHROPIC_API_KEY') client = anthropic.Anthropic(api_key=YOUR_API_TOKEN) class Role: SYSTEM = "system" USER = "user" ASSISTANT = "assistant" History = List[Tuple[str, str]] Messages = List[Dict[str, str]] def history_to_messages(history: History, system: str) -> Messages: messages = [{'role': Role.SYSTEM, 'content': system}] for h in history: messages.append({'role': Role.USER, 'content': h[0]}) messages.append({'role': Role.ASSISTANT, 'content': h[1]}) return messages def messages_to_history(messages: Messages) -> History: assert messages[0]['role'] == Role.SYSTEM history = [] for q, r in zip(messages[1::2], messages[2::2]): history.append([q['content'], r['content']]) return history def remove_code_block(text): pattern = r'```html\n(.+?)\n```' match = re.search(pattern, text, re.DOTALL) if match: return match.group(1).strip() else: return text.strip() def history_render(history: History): return gr.update(open=True), history def clear_history(): return [] def send_to_sandbox(code): encoded_html = base64.b64encode(code.encode('utf-8')).decode('utf-8') data_uri = f"data:text/html;charset=utf-8;base64,{encoded_html}" return f"" with gr.Blocks(css_paths="app.css") as demo: history = gr.State([]) setting = gr.State({ "system": SystemPrompt, }) def generation_code(query: Optional[str], _setting: Dict[str, str], _history: Optional[History]): if not query or query.strip() == '': query = random.choice(DEMO_LIST)['description'] # 빈 쿼리일 경우 랜덤 예제 사용 if _history is None: _history = [] messages = history_to_messages(_history, _setting['system']) system_message = messages[0]['content'] claude_messages = [ {"role": msg["role"] if msg["role"] != "system" else "user", "content": msg["content"]} for msg in messages[1:] + [{'role': Role.USER, 'content': query}] if msg["content"].strip() != '' # 빈 메시지 필터링 ] try: yield [ "Generating code...", _history, None, gr.update(active_key="loading"), gr.update(open=True) ] with client.messages.stream( model="claude-3-5-sonnet-20241022", max_tokens=7800, system=system_message, messages=claude_messages ) as stream: collected_content = "" for chunk in stream: if chunk.type == "content_block_delta": delta = chunk.delta.text collected_content += delta yield [ collected_content, _history, None, gr.update(active_key="loading"), gr.update(open=True) ] _history = messages_to_history([ {'role': Role.SYSTEM, 'content': system_message} ] + claude_messages + [{ 'role': Role.ASSISTANT, 'content': collected_content }]) yield [ collected_content, _history, send_to_sandbox(remove_code_block(collected_content)), gr.update(active_key="render"), gr.update(open=True) ] except Exception as e: print(f"Error details: {str(e)}") # 디버깅을 위한 에러 출력 raise ValueError(f'Error calling Claude API: {str(e)}') with ms.Application() as app: with antd.ConfigProvider(): # 메인 컨텐츠를 위한 Row with antd.Row(gutter=[32, 12]) as layout: # 좌측 패널 with antd.Col(span=24, md=8): with antd.Flex(vertical=True, gap="middle", wrap=True): header = gr.HTML(f"""

고양이도 발로 코딩하는 'MOUSE-I'

입력없이 'Send' 버튼 클릭시 랜덤한 예제 코드 생성. 생성된 코드만 프롬프트에 붙여넣고 'Code 실행' 버튼 클릭시 화면에 즉시 서비스가 실행. 문의: arxivgpt@gmail.com

""") input = antd.InputTextarea( size="large", allow_clear=True, placeholder=random.choice(DEMO_LIST)['description'] ) # 버튼들을 가로로 배치하기 위한 Flex 컨테이너 with antd.Flex(gap="small", justify="space-between"): btn = antd.Button("Send", type="primary", size="large") execute_btn = antd.Button("Code 실행", type="default", size="large") clear_btn = antd.Button("Clear", type="default", size="large") # Examples 버튼들 추가 antd.Divider("Try these examples") # 두 번째 예제 버튼 example_btn0 = antd.Button( "MBTI 진단 서비스", type="default", block=True, size="large" ) example_btn0.click( fn=lambda: "MBTI 진단을 위해 15개의 질문과 객관식 답변을 통해 MBTI 진단 결과 및 해당 성격에 대한 상세한 결과를 출력하라", inputs=[], outputs=[input] ) # 첫 번째 예제 버튼 example_btn1 = antd.Button( "다이나믹 차트 대쉬보드", type="default", block=True, size="large" ) example_btn1.click( fn=lambda: "Create an interactive dashboard with Chart.js showing different types of charts (line, bar, pie) with smooth animations. Include buttons to switch between different data views.", inputs=[], outputs=[input] ) # 두 번째 예제 버튼 example_btn2 = antd.Button( "[게임] 카드 기억력", type="default", block=True, size="large" ) example_btn2.click( fn=lambda: "Create a classic memory matching card game with flip animations. Include a scoring system, timer, and difficulty levels. Add satisfying match/mismatch animations and sound effects using Web Audio API.", inputs=[], outputs=[input] ) # Modal과 Drawer 컴포넌트들 with antd.Modal(open=False, title="set system Prompt", width="800px") as system_prompt_modal: systemPromptInput = antd.InputTextarea( SystemPrompt, auto_size=True) with antd.Drawer(open=False, title="code", placement="left", width="750px") as code_drawer: code_output = legacy.Markdown() with antd.Drawer(open=False, title="history", placement="left", width="900px") as history_drawer: history_output = legacy.Chatbot(show_label=False, flushing=False, height=960, elem_classes="history_chatbot") # 우측 패널 with antd.Col(span=24, md=16): with ms.Div(elem_classes="right_panel"): with antd.Flex(gap="small", elem_classes="setting-buttons"): settingPromptBtn = antd.Button( "⚙️ set system Prompt", type="default") codeBtn = antd.Button("🧑‍💻 view code", type="default") historyBtn = antd.Button("📜 history", type="default") gr.HTML('
') with antd.Tabs(active_key="empty", render_tab_bar="() => null") as state_tab: with antd.Tabs.Item(key="empty"): empty = antd.Empty(description="empty input", elem_classes="right_content") with antd.Tabs.Item(key="loading"): loading = antd.Spin(True, tip="coding...", size="large", elem_classes="right_content") with antd.Tabs.Item(key="render"): sandbox = gr.HTML(elem_classes="html_content") # Code 실행 버튼 이벤트 핸들러 def execute_code(query: str): if not query or query.strip() == '': return None, gr.update(active_key="empty") try: # HTML 코드 블록 확인 if '```html' in query and '```' in query: # HTML 코드 블록 추출 code = remove_code_block(query) else: # 입력된 텍스트를 그대로 코드로 사용 code = query.strip() return send_to_sandbox(code), gr.update(active_key="render") except Exception as e: print(f"Error executing code: {str(e)}") return None, gr.update(active_key="empty") # execute_btn 이벤트 핸들러 추가 execute_btn.click( fn=execute_code, inputs=[input], outputs=[sandbox, state_tab] ) settingPromptBtn.click(lambda: gr.update( open=True), inputs=[], outputs=[system_prompt_modal]) system_prompt_modal.ok(lambda input: ({"system": input}, gr.update( open=False)), inputs=[systemPromptInput], outputs=[setting, system_prompt_modal]) system_prompt_modal.cancel(lambda: gr.update( open=False), outputs=[system_prompt_modal]) codeBtn.click(lambda: gr.update(open=True), inputs=[], outputs=[code_drawer]) code_drawer.close(lambda: gr.update( open=False), inputs=[], outputs=[code_drawer]) historyBtn.click(history_render, inputs=[history], outputs=[history_drawer, history_output]) history_drawer.close(lambda: gr.update( open=False), inputs=[], outputs=[history_drawer]) btn.click( generation_code, inputs=[input, setting, history], outputs=[code_output, history, sandbox, state_tab, code_drawer] ) clear_btn.click(clear_history, inputs=[], outputs=[history]) if __name__ == "__main__": demo.queue(default_concurrency_limit=20).launch(ssr_mode=False)