from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain_core.messages import HumanMessage, ToolMessage

load_dotenv()
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

# (1) 정답 — 04_basic 과 동일한 구성 + 이름→도구 사전(dispatch 용)
calculator, wikipedia = load_tools(["llm-math", "wikipedia"], llm=llm)
llm_with_tools = llm.bind_tools([calculator, wikipedia])
tool_map = {"Calculator": calculator, "wikipedia": wikipedia}


# (2) 정답 — 선택 → 실행 → 최종답 한 사이클
def ask(q: str):
    print(f"\nQ: {q}")
    resp = llm_with_tools.invoke(q)
    if not resp.tool_calls:                       # 도구 불필요 → 바로 답
        print("  (도구 안 씀):", resp.content)
        return
    messages = [HumanMessage(q), resp]
    for call in resp.tool_calls:                  # LLM 이 고른 도구를 '이름으로 찾아' 실행
        print(f"  선택: {call['name']}({call['args']})")
        try:
            result = tool_map[call["name"]].invoke(call["args"])
        except Exception as e:
            result = f"도구 오류: {e}"
        messages.append(ToolMessage(content=str(result), tool_call_id=call["id"]))
    # 최종 답은 도구 없는 llm 으로 합성 (도구 바인딩된 걸로 하면 또 도구를 부르려 할 수 있음)
    # 이런 '도구→도구→…' 반복이 필요하면 06 create_agent 가 자동으로 돌려준다.
    print("  최종:", llm.invoke(messages).content)


if __name__ == "__main__":
    ask("53 * 7 + 2 는?")          # → 계산기 선택·실행
    ask("에펠탑은 누가 지었어?")     # → 위키백과 선택·실행
    ask("고마워!")                  # → 도구 안 씀
