Spaces:
Running
Running
| """Entry point for executing a graph step.""" | |
| import logging | |
| from dataclasses import asdict | |
| from typing import Dict, Optional | |
| import uuid | |
| from agent.utils import with_retries | |
| from agent.image_agent import generate_image_prompt | |
| from agent.tools import generate_scene_image | |
| from agent.llm_graph import GraphState, llm_game_graph | |
| from agent.models import UserState | |
| from agent.redis_state import get_user_state | |
| logger = logging.getLogger(__name__) | |
| async def process_step( | |
| user_hash: str, | |
| step: str, | |
| setting: Optional[str] = None, | |
| character: Optional[dict] = None, | |
| genre: Optional[str] = None, | |
| choice_text: Optional[str] = None, | |
| ) -> Dict: | |
| """Run one interaction step through the graph.""" | |
| logger.info("[Runner] Step %s for user %s", step, user_hash) | |
| graph_state = GraphState(user_hash=user_hash, step=step) | |
| if step == "start": | |
| assert setting and character and genre, "Missing start parameters" | |
| graph_state.setting = setting | |
| graph_state.character = character | |
| graph_state.genre = genre | |
| elif step == "choose": | |
| assert choice_text, "choice_text is required" | |
| graph_state.choice_text = choice_text | |
| final_state = await with_retries(lambda: llm_game_graph.ainvoke(asdict(graph_state))) | |
| user_state: UserState = await get_user_state(user_hash) | |
| response: Dict = {} | |
| ending = final_state.get("ending") | |
| if ending and ending.get("ending_reached"): | |
| ending_info = ending["ending"] | |
| if ( | |
| ("description" not in ending_info or not ending_info["description"]) | |
| and user_state.story_frame | |
| ): | |
| for e in user_state.story_frame.endings: | |
| if e.id == ending_info.get("id"): | |
| ending_info["description"] = e.description | |
| break | |
| ending_desc = ending_info.get("description") or ending_info.get( | |
| "condition", "" | |
| ) | |
| change_scene = await generate_image_prompt(user_hash, ending_desc) | |
| if change_scene.change_scene == "no_change": | |
| change_scene.change_scene = "change_completely" | |
| if not change_scene.scene_description: | |
| change_scene.scene_description = ending_desc | |
| image_path = await generate_scene_image.ainvoke( | |
| { | |
| "user_hash": user_hash, | |
| "scene_id": f"ending_{uuid.uuid4()}", | |
| "change_scene": change_scene, | |
| } | |
| ) | |
| response["ending"] = ending_info | |
| response["image"] = image_path | |
| response["game_over"] = True | |
| else: | |
| if ( | |
| user_state.current_scene_id | |
| and user_state.current_scene_id in user_state.scenes | |
| ): | |
| current_scene = user_state.scenes[ | |
| user_state.current_scene_id | |
| ].dict() | |
| else: | |
| current_scene = final_state.get("scene") | |
| response["scene"] = current_scene | |
| response["game_over"] = False | |
| return response | |