Guest User

Untitled

a guest
Aug 18th, 2025
17
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.28 KB | None | 0 0
  1. import os
  2. import json
  3. import asyncio
  4. import time
  5. from typing_extensions import TypedDict, Annotated
  6. import operator
  7. from langgraph.graph import StateGraph, START, END
  8. from langgraph.prebuilt import create_react_agent
  9. from langchain_openai import ChatOpenAI
  10. from langchain.schema import HumanMessage
  11. from langchain_core.runnables import RunnableLambda
  12. from dotenv import load_dotenv
  13.  
  14. load_dotenv()
  15. OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
  16. if not OPENAI_API_KEY:
  17. raise ValueError("OPENAI_API_KEY not in.env")
  18.  
  19. class State(TypedDict):
  20. results: Annotated[list[str], operator.add] # accumulator
  21. choice: str
  22.  
  23. llm = ChatOpenAI(model="gpt-4o", openai_api_key=OPENAI_API_KEY)
  24.  
  25. async def decision_node(state: State):
  26. module_start_time = int(time.time())
  27. print(".: Decision Node .:")
  28. prompt = (
  29. "Decide aleatoriamente que nodos ejecutar para crear una canción. "
  30. "favorece responder con both la mayor parte de las veces"
  31. "Responde unicament con uno de estos valores: 'poem', 'melody', 'both'."
  32. )
  33. # Usar ainvoke para llamada async
  34. response = await llm.ainvoke([HumanMessage(content=prompt)])
  35. choice = response.content.strip().lower()
  36. print(f"Decisión LLM: {choice}")
  37. if choice not in {"poem", "melody", "both"}:
  38. print("Got a wrong result from llm ->", choice, "<- will set both")
  39. choice = "both"
  40.  
  41. print("Returining this choice ->", choice)
  42. spent_time = int(time.time()) - module_start_time
  43. print("- Spent time - ", spent_time)
  44. return {"choice": choice}
  45.  
  46.  
  47.  
  48. # Función para enrutar condicionalmente según la decisión LLM
  49. def route_nodes(state: State):
  50. choice = state.get("choice", "both")
  51. if choice == "poem":
  52. return ["poem_agent"]
  53. elif choice == "melody":
  54. return ["melody_agent"]
  55. else:
  56. return ["poem_agent", "melody_agent"]
  57.  
  58. # Crear agentes ReAct con create_react_agent para poema y melodía
  59. poem_agent = create_react_agent(
  60. model=llm,
  61. tools=[],
  62. prompt="Eres un asistente que crea poemas cortos y emotivos ideales para crear canciones pop."
  63. )
  64.  
  65. melody_agent = create_react_agent(
  66. model=llm,
  67. tools=[],
  68. prompt="Eres un asistente que describe melodías alegres y pegadizas para canciones pop."
  69. )
  70.  
  71. composer_prompt = """
  72. Eres un asistente experto en música que debe crear una cacnion a partir de un poema y una melodía.
  73.  
  74. Genera una idea musical basada en una progresión de acordes popular, como I–V–vi–IV o una variante del Canon de Pachelbel. Usa una tonalidad mayor. Incluye lo siguiente en la salida, en formato JSON estructurado:
  75.  
  76. style: una descripción corta del estilo o ambiente emocional.
  77. key: tonalidad (por ejemplo, C, G, D).
  78. tempo: valor en BPM.
  79. time_signature: compás (por ejemplo, 4/4).
  80. chord_progression: lista de acordes, uno por compás.
  81. abc_notation: campo con la melodía escrita en notación ABC completa.
  82. comments: una breve descripción artística del resultado.
  83.  
  84. no respondas con backick ni tags json, solo el resultado del json convierte toda la salida a ascii puro
  85.  
  86. """
  87.  
  88. composer_agent = create_react_agent(
  89. model=llm,
  90. tools=[],
  91. prompt=composer_prompt
  92. )
  93.  
  94. # Wrappers async para usar los agentes como nodos
  95. async def async_composer_agent(state: State):
  96. module_start_time = int(time.time())
  97. print(".: Song Maker react node .:")
  98. poem = ""
  99. melody = ""
  100. for r in state.get("results", []):
  101. if r.startswith("Poema:"):
  102. poem = r[len("Poema:"):].strip()
  103. elif r.startswith("Melodía:"):
  104. melody = r[len("Melodía:"):].strip()
  105.  
  106. input_text = f"Poema:\n{poem}\n\nMelodía:\n{melody}\n\nPor favor, crea una bonita cancion con esos datos."
  107. messages = [{"role": "user", "content": input_text}]
  108. response = await composer_agent.ainvoke({"messages": messages})
  109. content = response["messages"][-1].content
  110.  
  111. try:
  112. json_content = json.loads(content)
  113. except:
  114. print("Cant load json content ->:", content)
  115. json_content={}
  116. print("Descripción de la canción generada")
  117. print("Generated song")
  118. print(json_content['abc_notation'])
  119. print("---------------------------")
  120. spent_time = int(time.time()) - module_start_time
  121. print("- Spent time - ", spent_time)
  122. return {"results": [f"Descripción de la canción:\n{content}"]}
  123.  
  124. async def async_poem_agent(state: State):
  125. module_start_time = int(time.time())
  126. print(".: Poem Maker react node .:")
  127. messages = [{"role": "user", "content": "Por favor, crea un poema, ideal para una cancion popular`"}]
  128. response = await poem_agent.ainvoke({"messages": messages})
  129. content = response["messages"][-1].content
  130. print("Poema generado")
  131. print("Returning this data ->", content)
  132. spent_time = int(time.time()) - module_start_time
  133. print("- Spent time - ", spent_time)
  134. return {"results": [f"Poema:\n{content}"]}
  135.  
  136. async def async_melody_agent(state: State):
  137. module_start_time = int(time.time())
  138. print(".: Melody Maker react node .:")
  139. messages = [{"role": "user", "content": "Por favor, describe una melodía alegre y pegadiza para una canción pop."}]
  140. response = await melody_agent.ainvoke({"messages": messages})
  141. content = response["messages"][-1].content
  142. print("Melodía generada")
  143. print("Returning this data ->", content)
  144. spent_time = int(time.time()) - module_start_time
  145. print("- Spent time - ", spent_time)
  146. return {"results": [f"Melodía:\n{content}"]}
  147.  
  148.  
  149. # Graph build
  150. builder = StateGraph(State)
  151.  
  152. builder.add_node("decision_node", RunnableLambda(func=decision_node))
  153. builder.add_node("poem_agent", RunnableLambda(func=async_poem_agent))
  154. builder.add_node("melody_agent", RunnableLambda(func=async_melody_agent))
  155. builder.add_node("composer_agent", RunnableLambda(func=async_composer_agent))
  156.  
  157.  
  158. builder.add_edge(START, "decision_node")
  159. builder.add_conditional_edges("decision_node", route_nodes)
  160. builder.add_edge("poem_agent", "composer_agent")
  161. builder.add_edge("melody_agent", "composer_agent")
  162. builder.add_edge("composer_agent", END)
  163.  
  164. graph = builder.compile()
  165.  
  166. async def main():
  167. result = await graph.ainvoke({"results": [], "choice": ""})
  168. #print("\nResultado final del grafo:\n", result)
  169.  
  170. if __name__ == "__main__":
  171. asyncio.run(main())
Advertisement
Add Comment
Please, Sign In to add comment