Files
wehub-resource-sync 85742ab165
Deploy Documentation / deploy (push) Has been cancelled
CPU Test / Test (Utilities, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (LLM proxy, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Others, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Store, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Utilities, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Weave, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (AgentOps, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (LLM proxy, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Others, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Weave, latest, Python 3.13) (push) Has been cancelled
Dashboard / Chromatic (push) Has been cancelled
CPU Test / Lint - fast (push) Has been cancelled
CPU Test / Lint - next (push) Has been cancelled
CPU Test / Lint - slow (push) Has been cancelled
CPU Test / Lint - JavaScript (push) Has been cancelled
CPU Test / Build documentation (push) Has been cancelled
CPU Test / Test (AgentOps, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (LLM proxy, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Others, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Store, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Weave, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (AgentOps, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Store, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Utilities, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Weave, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (AgentOps, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (LLM proxy, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Others, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Store, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Utilities, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (JavaScript) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:44:17 +08:00

184 lines
6.1 KiB
Python

# Copyright (c) Microsoft. All rights reserved.
from typing import Optional
from autogen_core.models import AssistantMessage, UserMessage
class HistoryPromptBuilder:
"""
Builds prompts using a history of observations and actions.
Supports two prompt styles:
- chat: multi-turn user/assistant messages
- single: a single formatted prompt with optional history
"""
def __init__(self, max_history: int = -1, prompt_type: str = "chat"):
"""
Args:
max_history (int): Maximum number of past steps to include
(-1 means unlimited).
prompt_type (str): Prompt style ("chat" or "single").
"""
self.max_history = max_history
self.prompt_type = prompt_type
self._events = []
self.admissible_actions = None
self.step_count = 1
def update_step_count(self):
"""Increment the current step counter."""
self.step_count += 1
def update_instruction_prompt(self, instruction: str):
"""Set the instruction/system prompt used in chat mode."""
self.instruction = instruction
def update_single_obs_template(self, single_obs_template_wo_his: str, single_obs_template: str):
"""
Set templates for single-prompt mode.
Args:
single_obs_template_wo_his (str): Template without history.
single_obs_template (str): Template with history.
"""
self.single_obs_template_wo_his = single_obs_template_wo_his
self.single_obs_template = single_obs_template
def update_observation(self, obs: dict):
"""Append an observation to the event history."""
self._events.append(
{
"type": "observation",
"text": obs,
}
)
def update_action(self, action: str):
"""Append an action to the event history."""
self._events.append(
{
"type": "action",
"action": action,
}
)
def update_admissible_actions(self, admissible_actions):
"""Update the list of admissible actions for the current step."""
self.admissible_actions = admissible_actions
def init(self, env):
"""
Initialize the prompt builder at the beginning of an episode.
- Clears the event history
- Loads prompt instructions or templates from the environment
"""
self._events.clear()
if self.prompt_type == "chat":
inst_prompt = env.get_instruction_prompt()
self.update_instruction_prompt(inst_prompt)
elif self.prompt_type == "single":
template_wo_his, template = env.get_single_prompt_template()
self.update_single_obs_template(template_wo_his, template)
else:
raise ValueError(f"Unsupported prompt_type: {self.prompt_type}")
def get_chat_prompt(self):
"""
Construct a chat-style prompt from the event history.
Returns:
List[Message]: A sequence of User and Assistant messages.
"""
if self.max_history != -1:
events = self._events[-(self.max_history * 2 + 1) :]
else:
events = self._events
messages = []
for idx, event in enumerate(events):
event_type = event.get("type")
message = None
if event_type == "observation":
content = event.get("text", "")
# Attach instruction prompt to the first observation
if idx == 0 and self.instruction:
content += "\n" + self.instruction
message = UserMessage(source="user", content=content)
elif event_type == "action":
content = event.get("action", "")
message = AssistantMessage(source="assistant", content=content)
if message:
messages.append(message)
return messages
def get_single_prompt(self):
"""
Construct a single formatted prompt using templates.
Returns:
List[Message]: A single User message.
"""
if self.max_history != -1:
events = self._events[-(self.max_history * 2 + 1) :]
else:
events = self._events
current_obs = events[-1]["text"]
# Case 1: No history available
if len(events) == 1:
template = self.single_obs_template_wo_his
kwargs = {"current_observation": current_obs}
if "{admissible_actions}" in template:
kwargs["admissible_actions"] = self.admissible_actions
single_prompt = template.format(**kwargs)
# Case 2: History exists
else:
template = self.single_obs_template
history = ""
obs_count = 0
for idx, event in enumerate(events):
if events[idx]["type"] == "observation" and idx != len(events) - 1:
next_event = events[idx + 1]
history += f"[Observation {max(self.step_count-self.max_history+obs_count, 1)}: '{event['text']}', "
history += (
f"Action {max(self.step_count-self.max_history+obs_count, 1)}: '{next_event['action']}']\n "
)
obs_count += 1
kwargs = {
"step_count": self.step_count - 1,
"history_length": min(self.step_count - 1, self.max_history),
"history": history,
"current_step": self.step_count,
"current_observation": current_obs,
}
if "{admissible_actions}" in template:
kwargs["admissible_actions"] = self.admissible_actions
single_prompt = template.format(**kwargs)
return [UserMessage(source="user", content=single_prompt)]
def get_prompt(self):
"""
Return the final prompt based on the configured prompt type.
"""
if self.prompt_type == "chat":
prompt = self.get_chat_prompt()
elif self.prompt_type == "single":
prompt = self.get_single_prompt()
return prompt