use LLM agent as fallback if player does not respond, fix various client bugs
This commit is contained in:
parent
580076335f
commit
f2185344b1
|
@ -5,6 +5,7 @@ from readline import add_history
|
|||
from typing import Any, Callable, Dict, List, Sequence
|
||||
|
||||
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
|
||||
from packit.agent import Agent
|
||||
from packit.utils import could_be_json
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
@ -111,13 +112,15 @@ class LocalPlayer(BasePlayer):
|
|||
|
||||
|
||||
class RemotePlayer(BasePlayer):
|
||||
fallback_agent: Agent | None
|
||||
input_queue: Queue[str]
|
||||
send_prompt: Callable[[str, str], bool]
|
||||
|
||||
def __init__(
|
||||
self, name: str, backstory: str, send_prompt: Callable[[str, str], bool]
|
||||
self, name: str, backstory: str, send_prompt: Callable[[str, str], bool], fallback_agent = None
|
||||
) -> None:
|
||||
super().__init__(name, backstory)
|
||||
self.fallback_agent = fallback_agent
|
||||
self.input_queue = Queue()
|
||||
self.send_prompt = send_prompt
|
||||
|
||||
|
@ -138,4 +141,7 @@ class RemotePlayer(BasePlayer):
|
|||
except Exception:
|
||||
logger.exception("error getting reply from remote player")
|
||||
|
||||
if self.fallback_agent:
|
||||
return self.fallback_agent(prompt, **kwargs)
|
||||
|
||||
return ""
|
||||
|
|
|
@ -7,7 +7,6 @@ from typing import Dict
|
|||
from uuid import uuid4
|
||||
|
||||
import websockets
|
||||
from packit.agent import Agent
|
||||
|
||||
from adventure.context import get_actor_agent_for_name, set_actor_agent_for_name
|
||||
from adventure.models import Actor, Room, World
|
||||
|
@ -18,7 +17,6 @@ logger = getLogger(__name__)
|
|||
|
||||
connected = set()
|
||||
characters: Dict[str, RemotePlayer] = {}
|
||||
previous_agents: Dict[str, Agent] = {}
|
||||
recent_events = deque(maxlen=100)
|
||||
recent_world = None
|
||||
|
||||
|
@ -63,7 +61,7 @@ async def handler(websocket):
|
|||
try:
|
||||
# if this socket is attached to a character and that character's turn is active, wait for input
|
||||
message = await websocket.recv()
|
||||
logger.info(f"Received message: {message}")
|
||||
logger.info(f"Received message for {id}: {message}")
|
||||
|
||||
try:
|
||||
data = loads(message)
|
||||
|
@ -86,13 +84,12 @@ async def handler(websocket):
|
|||
continue
|
||||
|
||||
# player_name = data["player"]
|
||||
player = RemotePlayer(actor.name, actor.backstory, sync_turn)
|
||||
player = RemotePlayer(actor.name, actor.backstory, sync_turn, fallback_agent=llm_agent)
|
||||
characters[id] = player
|
||||
logger.info(f"Client {websocket} is now character {character_name}")
|
||||
|
||||
# swap out the LLM agent
|
||||
set_actor_agent_for_name(actor.name, actor, player)
|
||||
previous_agents[actor.name] = llm_agent
|
||||
|
||||
# notify all clients that this character is now active
|
||||
send_and_append(
|
||||
|
@ -117,7 +114,7 @@ async def handler(websocket):
|
|||
|
||||
actor, _ = get_actor_agent_for_name(player.name)
|
||||
if actor:
|
||||
set_actor_agent_for_name(player.name, actor, previous_agents[player.name])
|
||||
set_actor_agent_for_name(player.name, actor, player.fallback_agent)
|
||||
|
||||
logger.info("Client disconnected")
|
||||
|
||||
|
|
|
@ -82,8 +82,7 @@ export function App(props: AppProps) {
|
|||
const { lastMessage, readyState, sendMessage } = useWebSocket(props.socketUrl);
|
||||
|
||||
function setPlayer(actor: Maybe<Actor>) {
|
||||
setCharacter(actor);
|
||||
|
||||
// do not setCharacter until the server confirms the player change
|
||||
if (doesExist(actor)) {
|
||||
sendMessage(JSON.stringify({ type: 'player', become: actor.name }));
|
||||
}
|
||||
|
@ -92,6 +91,7 @@ export function App(props: AppProps) {
|
|||
function sendInput(input: string) {
|
||||
if (doesExist(character)) {
|
||||
sendMessage(JSON.stringify({ type: 'input', input }));
|
||||
setActiveTurn(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ export function PlayerPanel(props: PlayerPanelProps) {
|
|||
|
||||
return <Card>
|
||||
<CardContent>
|
||||
<Stack direction="column" spacing={2}>
|
||||
{activeTurn && <Alert severity="warning">It's your turn!</Alert>}
|
||||
<Typography variant="h6">Playing as: {actor.name}</Typography>
|
||||
<Typography variant="body1">{actor.backstory}</Typography>
|
||||
|
@ -35,6 +36,7 @@ export function PlayerPanel(props: PlayerPanelProps) {
|
|||
sendInput(input);
|
||||
}}>Send</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</Card>;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ export function ItemItem(props: { item: Item } & BaseEntityItemProps) {
|
|||
export function ActorItem(props: { actor: Actor } & BaseEntityItemProps) {
|
||||
const { actor, activeCharacter, setDetails, setPlayer } = props;
|
||||
|
||||
const active = doesExist(activeCharacter) && actor === activeCharacter;
|
||||
const active = doesExist(activeCharacter) && actor.name === activeCharacter.name;
|
||||
const label = formatLabel(actor.name, active);
|
||||
|
||||
let playButton;
|
||||
|
@ -79,7 +79,7 @@ export function ActorItem(props: { actor: Actor } & BaseEntityItemProps) {
|
|||
export function RoomItem(props: { room: Room } & BaseEntityItemProps) {
|
||||
const { room, activeCharacter, setDetails, setPlayer } = props;
|
||||
|
||||
const active = doesExist(activeCharacter) && room.actors.some((it) => it === activeCharacter);
|
||||
const active = doesExist(activeCharacter) && room.actors.some((it) => it.name === activeCharacter.name);
|
||||
const label = formatLabel(room.name, active);
|
||||
|
||||
return <TreeItem itemId={room.name} label={label}>
|
||||
|
|
Loading…
Reference in New Issue