# pixal_agent_full.py import os import datetime import gradio as gr import requests from typing import Optional, List from langchain.llms.base import LLM from langchain.agents import initialize_agent, AgentType,load_tools from langchain.tools import Tool from langchain_experimental.tools.python.tool import PythonREPLTool from langchain_community.retrievers import WikipediaRetriever from langchain.tools.retriever import create_retriever_tool retriever = WikipediaRetriever() retriever_tool = create_retriever_tool( retriever, name="wiki_search", description="위키백과에서 필요한 정보를 불러옵니다.결괴를 검증하여 사용하시오.", ) # ────────────────────────────── # ✅ GitHub Models LLM # ────────────────────────────── class GitHubModelLLM(LLM): model: str = "openai/gpt-4.1" endpoint: str = "https://models.github.ai/inference" token: Optional[str] = None @property def _llm_type(self) -> str: return "github_models_api" def _call(self, prompt: str, stop: Optional[List[str]] = None) -> str: if not self.token: raise ValueError("GitHub API token이 필요합니다.") headers = { "Authorization": f"Bearer {self.token}", "Content-Type": "application/json", } body = {"model": self.model, "messages": [{"role": "user", "content": prompt}]} resp = requests.post(f"{self.endpoint}/chat/completions", json=body, headers=headers) if resp.status_code != 200: raise ValueError(f"API 오류: {resp.status_code} - {resp.text}") return resp.json()["choices"][0]["message"]["content"] # ────────────────────────────── # ✅ LLM 설정 # ────────────────────────────── token = os.getenv("GITHUB_TOKEN") or os.getenv("token") if not token: print("⚠️ GitHub Token이 필요합니다. 예: setx GITHUB_TOKEN your_token") llm = GitHubModelLLM(model="openai/gpt-4.1", token=token) # ────────────────────────────── # ✅ LangChain 기본 도구 불러오기 # ────────────────────────────── tools = load_tools( ["ddg-search", "requests_all", "llm-math"], llm=llm,allow_dangerous_tools=True )+[retriever_tool] # ────────────────────────────── # ✅ Python 실행 도구 (LangChain 내장) # ────────────────────────────── python_tool = PythonREPLTool() tools.append(Tool(name="python_repl", func=python_tool.run, description="Python 코드를 실행합니다.")) # ────────────────────────────── # ✅ 파일 도구 # ────────────────────────────── BASE_DIR = os.path.join(os.getcwd(), "pixal_files") os.makedirs(BASE_DIR, exist_ok=True) def file_write(data: str) -> str: try: name, content = data.split("\n", 1) path = os.path.join(BASE_DIR, name.strip()) with open(path, "w", encoding="utf-8") as f: f.write(content) return f"✅ 파일 저장됨: {path}" except Exception as e: return f"⚠️ 파일 저장 오류: {e}" def file_read(filename: str) -> str: path = os.path.join(BASE_DIR, filename.strip()) if not os.path.exists(path): return "❌ 파일 없음" with open(path, "r", encoding="utf-8") as f: return f.read() def file_list(_="") -> str: return "\n".join(os.listdir(BASE_DIR)) def file_delete(filename: str) -> str: path = os.path.join(BASE_DIR, filename.strip()) if os.path.exists(path): os.remove(path) return f"🗑️ 삭제 완료: {filename}" return "❌ 파일 없음" # ────────────────────────────── # ✅ 시간 도구 # ────────────────────────────── def time_now(_=""): now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))) return f"현재 시각: {now.strftime('%Y-%m-%d %H:%M:%S')} (Asia/Seoul)" # ────────────────────────────── # ✅ 도구 등록 # ────────────────────────────── tools.extend([ Tool(name="file_write", func=file_write, description="파일을 생성/수정합니다."), Tool(name="file_read", func=file_read, description="파일 내용을 읽습니다."), Tool(name="file_list", func=file_list, description="파일 목록을 표시합니다."), Tool(name="file_delete", func=file_delete, description="파일을 삭제합니다."), Tool(name="time_now", func=time_now, description="현재 시간을 반환합니다."), ]) # ────────────────────────────── # ✅ Agent 초기화 # ────────────────────────────── agent = initialize_agent( tools, llm, agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True ) # ────────────────────────────── # ✅ Gradio UI # ────────────────────────────── def chat(message, history): try: response = agent.run(message) except Exception as e: response = f"⚠️ 오류: {e}" history = history + [(message, response)] return history, history with gr.Blocks(theme=gr.themes.Soft(), title="PIXAL Assistant (LangChain + GitHub LLM)") as demo: gr.Markdown(""" ## 🤖 PIXAL Assistant **LangChain 기반 멀티툴 에이전트** 🧰 DuckDuckGo · Wikipedia · YouTube · Math · Requests · Python REPL · File · Time """) chatbot = gr.Chatbot(label="PIXAL 대화", height=600, latex=True) msg = gr.Textbox(label="메시지", placeholder="명령 또는 질문을 입력하세요...") clear = gr.Button("초기화") msg.submit(chat, [msg, chatbot], [chatbot, chatbot]) clear.click(lambda: None, None, chatbot, queue=False) if __name__ == "__main__": demo.launch(server_name="0.0.0.0", server_port=7860)