mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-08-28 05:25:04 +00:00
【bugfix】part one
This commit is contained in:
parent
fe162d32d6
commit
5874c33c87
13 changed files with 79 additions and 399 deletions
4
TODO.md
4
TODO.md
|
|
@ -27,4 +27,6 @@
|
|||
# 锦鲤
|
||||
1. LOGO更加简洁 agent <-> experience
|
||||
2. default等名字的说明
|
||||
3. 查看所有的op代码
|
||||
3. 查看所有的op代码
|
||||
4. ba增加client
|
||||
5. 在appworld上跑
|
||||
|
|
@ -12,6 +12,7 @@ class BaseEmbeddingModel(BaseModel, ABC):
|
|||
dimensions: int = Field(default=..., description="dimensions")
|
||||
max_retries: int = Field(default=3, description="max retries")
|
||||
raise_exception: bool = Field(default=True, description="raise exception")
|
||||
max_batch_size: int = Field(default=10, description="text-embedding-v4 batch size should not be larger than 10")
|
||||
|
||||
def _get_embeddings(self, input_text: str | List[str]):
|
||||
raise NotImplementedError
|
||||
|
|
@ -34,9 +35,9 @@ class BaseEmbeddingModel(BaseModel, ABC):
|
|||
return nodes
|
||||
|
||||
elif isinstance(nodes, list):
|
||||
max_batch_size = 10 # text-embedding-v4 batch size should not be larger than 10
|
||||
embeddings = [emb for i in range(0, len(nodes), max_batch_size) for emb in
|
||||
self.get_embeddings(input_text=[node.content for node in nodes[i:i + max_batch_size]])]
|
||||
|
||||
embeddings = [emb for i in range(0, len(nodes), self.max_batch_size) for emb in
|
||||
self.get_embeddings(input_text=[node.content for node in nodes[i:i + self.max_batch_size]])]
|
||||
if len(embeddings) != len(nodes):
|
||||
logger.warning(f"embeddings.size={len(embeddings)} <> nodes.size={len(nodes)}")
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class BaseLLM(BaseModel, ABC):
|
|||
parallel_tool_calls: bool = Field(default=True)
|
||||
|
||||
max_retries: int = Field(default=5, description="max retries")
|
||||
raise_exception: bool = Field(default=True, description="raise exception")
|
||||
raise_exception: bool = Field(default=False, description="raise exception")
|
||||
|
||||
def stream_chat(self, messages: List[Message], tools: List[BaseTool] = None, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
|
@ -35,7 +35,8 @@ class BaseLLM(BaseModel, ABC):
|
|||
def _chat(self, messages: List[Message], tools: List[BaseTool] = None, **kwargs) -> Message:
|
||||
raise NotImplementedError
|
||||
|
||||
def chat(self, messages: List[Message], tools: List[BaseTool] = None, callback_fn: Callable = None, **kwargs):
|
||||
def chat(self, messages: List[Message], tools: List[BaseTool] = None, callback_fn: Callable = None,
|
||||
default_value=None, **kwargs):
|
||||
for i in range(self.max_retries):
|
||||
try:
|
||||
message: Message = self._chat(messages, tools, **kwargs)
|
||||
|
|
@ -48,7 +49,10 @@ class BaseLLM(BaseModel, ABC):
|
|||
logger.exception(f"chat with model={self.model_name} encounter error with e={e.args}")
|
||||
time.sleep(1 + i)
|
||||
|
||||
if i == self.max_retries - 1 and self.raise_exception:
|
||||
raise e
|
||||
if i == self.max_retries - 1:
|
||||
if self.raise_exception:
|
||||
raise e
|
||||
else:
|
||||
return default_value
|
||||
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -76,7 +76,12 @@ class BaseOp(PromptMixin, ABC):
|
|||
def join_task(self, task_desc: str = None) -> list:
|
||||
result = []
|
||||
for task in tqdm(self.task_list, desc=task_desc or (self.simple_name + ".join_task")):
|
||||
result.append(task.result())
|
||||
t_result = task.result()
|
||||
if t_result:
|
||||
if isinstance(t_result, list):
|
||||
result.extend(t_result)
|
||||
else:
|
||||
result.append(t_result)
|
||||
self.task_list.clear()
|
||||
return result
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class RewriteExperienceOp(BaseOp):
|
|||
|
||||
|
||||
def _generate_context_message(self, query: str, messages: List[Message], nodes: List[VectorNode],
|
||||
retrieval_query: str) -> Message:
|
||||
retrieval_query: str) -> str:
|
||||
"""Generate context message from retrieved experiences"""
|
||||
if not nodes:
|
||||
return ""
|
||||
|
|
|
|||
|
|
@ -57,10 +57,7 @@ class SimpleSummaryOp(BaseOp):
|
|||
for trajectory in request.traj_list:
|
||||
self.submit_task(self.summary_trajectory, trajectory=trajectory)
|
||||
|
||||
experience_list: List[BaseExperience] = []
|
||||
for task_result in self.join_task():
|
||||
if task_result:
|
||||
experience_list.extend(task_result)
|
||||
experience_list: List[BaseExperience] = self.join_task()
|
||||
|
||||
response: SummarizerResponse = self.context.response
|
||||
response.experience_list = experience_list
|
||||
|
|
@ -68,4 +65,4 @@ class SimpleSummaryOp(BaseOp):
|
|||
logger.info(f"add experience when_to_use={e.when_to_use}\ncontent={e.content}")
|
||||
|
||||
from experiencemaker.op.vector_store.update_vector_store_op import UpdateVectorStoreOp
|
||||
self.context.set_context(UpdateVectorStoreOp.INSERT_NODES, [x.to_vector_node() for x in experience_list])
|
||||
self.context.set_context(UpdateVectorStoreOp.INSERT_EXPERIENCE_LIST, [x.to_vector_node() for x in experience_list])
|
||||
|
|
|
|||
|
|
@ -1,274 +0,0 @@
|
|||
success_step_experience_prompt: |
|
||||
You are an expert AI analyst reviewing successful step sequences from an AI agent execution.
|
||||
|
||||
Your task is to extract reusable, actionable step-level experiences that can guide future agent executions.
|
||||
Focus on identifying specific patterns, techniques, and decision points that contributed to success.
|
||||
|
||||
ANALYSIS FRAMEWORK:
|
||||
● STEP PATTERN ANALYSIS: Identify the specific sequence of actions that led to success
|
||||
● DECISION POINTS: Highlight critical decisions made during these steps
|
||||
● TECHNIQUE EFFECTIVENESS: Analyze why specific approaches worked well
|
||||
● REUSABILITY: Extract patterns that can be applied to similar scenarios
|
||||
|
||||
EXTRACTION PRINCIPLES:
|
||||
● Focus on TRANSFERABLE TECHNIQUES and decision frameworks
|
||||
● Frame insights as actionable guidelines and best practices
|
||||
|
||||
# Original Query
|
||||
{query}
|
||||
|
||||
# Step Sequence Analysis
|
||||
{step_sequence}
|
||||
|
||||
# Context Information
|
||||
{context}
|
||||
|
||||
# Outcome
|
||||
This step sequence was part of a {outcome} trajectory.
|
||||
|
||||
OUTPUT FORMAT:
|
||||
Generate 1-3 step-level success insights as JSON objects:
|
||||
```json
|
||||
[
|
||||
{{
|
||||
"when_to_use": "Specific conditions when this step pattern should be applied",
|
||||
"experience": "Detailed description of the successful step pattern and why it works",
|
||||
"tags": ["relevant", "keywords", "for", "categorization"],
|
||||
"confidence": 0.8,
|
||||
"step_type": "reasoning|action|observation|decision",
|
||||
"tools_used": ["list", "of", "tools"]
|
||||
}}
|
||||
]
|
||||
```
|
||||
|
||||
failure_step_experience_prompt: |
|
||||
You are an expert AI analyst reviewing failed step sequences from an AI agent execution.
|
||||
|
||||
Your task is to extract learning experiences from failures to prevent similar mistakes in future executions.
|
||||
Focus on identifying error patterns, missed opportunities, and alternative approaches.
|
||||
|
||||
ANALYSIS FRAMEWORK:
|
||||
● FAILURE POINT IDENTIFICATION: Pinpoint where and why the steps went wrong
|
||||
● ERROR PATTERN ANALYSIS: Identify recurring mistakes or problematic approaches
|
||||
● ALTERNATIVE APPROACHES: Suggest what could have been done differently
|
||||
● PREVENTION STRATEGIES: Extract actionable insights to avoid similar failures
|
||||
|
||||
EXTRACTION PRINCIPLES:
|
||||
● Extract GENERAL PRINCIPLES as well as SPECIFIC INSTRUCTIONS
|
||||
● Focus on PATTERNS and RULES as well as particular instances
|
||||
|
||||
# Original Query
|
||||
{query}
|
||||
|
||||
# Step Sequence Analysis
|
||||
{step_sequence}
|
||||
|
||||
# Context Information
|
||||
{context}
|
||||
|
||||
# Outcome
|
||||
This step sequence was part of a {outcome} trajectory.
|
||||
|
||||
OUTPUT FORMAT:
|
||||
Generate 1-3 step-level failure prevention insights as JSON objects:
|
||||
```json
|
||||
[
|
||||
{{
|
||||
"when_to_use": "Specific situations where this lesson should be remembered",
|
||||
"experience": "Universal principle or rule extracted from the failure pattern ",
|
||||
"tags": ["error_prevention", "failure_analysis", "relevant_keywords"],
|
||||
"confidence": 0.7,
|
||||
"step_type": "reasoning|action|observation|decision",
|
||||
"tools_used": ["list", "of", "tools"]
|
||||
}}
|
||||
]
|
||||
```
|
||||
|
||||
comparative_step_experience_prompt: |
|
||||
You are an expert AI analyst comparing successful and failed step sequences to extract differential insights.
|
||||
|
||||
Your task is to identify the key differences between success and failure patterns at the step level.
|
||||
Focus on critical decision points, technique variations, and approach differences.
|
||||
|
||||
COMPARATIVE ANALYSIS FRAMEWORK:
|
||||
● DECISION CONTRAST: Compare critical decisions made in success vs failure cases
|
||||
● TECHNIQUE VARIATIONS: Identify different approaches and their outcomes
|
||||
● TIMING DIFFERENCES: Analyze when certain actions were taken and their impact
|
||||
● SUCCESS FACTORS: Extract what specifically made the difference
|
||||
|
||||
EXTRACTION PRINCIPLES:
|
||||
● Frame comparisons as PRINCIPLES as well as case-specific SOLUTIONS
|
||||
● Identify PATTERNS that differentiate effective vs ineffective approaches
|
||||
● Extract RULES that can guide future similar situations
|
||||
● Focus on UNDERLYING MECHANISMS rather than surface-level differences
|
||||
|
||||
# Successful Step Sequence
|
||||
{success_steps}
|
||||
|
||||
# Failed Step Sequence
|
||||
{failure_steps}
|
||||
|
||||
# Similarity Score: {similarity_score}
|
||||
|
||||
OUTPUT FORMAT:
|
||||
Generate 1-2 comparative insights as JSON objects:
|
||||
```json
|
||||
[
|
||||
{{
|
||||
"when_to_use": "Specific scenarios where this comparative insight applies",
|
||||
"experience": "Detailed comparison highlighting why success approach works better",
|
||||
"tags": ["comparative_analysis", "success_factors", "relevant_keywords"],
|
||||
"confidence": 0.8,
|
||||
"step_type": "reasoning|action|observation|decision"
|
||||
}}
|
||||
]
|
||||
```
|
||||
|
||||
general_step_experience_prompt: |
|
||||
You are an expert AI analyst reviewing step sequences to extract general patterns and insights.
|
||||
|
||||
Your task is to identify valuable step-level patterns without explicit success/failure labels.
|
||||
Focus on effective techniques, common patterns, and general best practices.
|
||||
|
||||
ANALYSIS FRAMEWORK:
|
||||
● PATTERN RECOGNITION: Identify recurring effective patterns in the steps
|
||||
● TECHNIQUE ANALYSIS: Analyze the effectiveness of different approaches
|
||||
● BEST PRACTICES: Extract general principles that appear beneficial
|
||||
● APPLICABILITY: Determine when these patterns would be most useful
|
||||
|
||||
GENERALIZATION PRINCIPLES:
|
||||
● Extract UNIVERSAL PATTERNS that transcend specific contexts
|
||||
● Identify TRANSFERABLE METHODOLOGIES and approaches
|
||||
● Focus on PRINCIPLE-LEVEL insights as well as tactical details
|
||||
● Formulate insights as REUSABLE FRAMEWORKS and guidelines
|
||||
|
||||
GENERALIZATION PRINCIPLES:
|
||||
● Extract UNIVERSAL PATTERNS that transcend specific contexts
|
||||
● Identify TRANSFERABLE METHODOLOGIES and approaches
|
||||
● Focus on PRINCIPLE-LEVEL insights
|
||||
● Formulate insights as REUSABLE FRAMEWORKS and guidelines
|
||||
|
||||
# Original Query
|
||||
{query}
|
||||
|
||||
# Step Sequence Analysis
|
||||
{step_sequence}
|
||||
|
||||
# Context Information
|
||||
{context}
|
||||
|
||||
OUTPUT FORMAT:
|
||||
Generate 1-2 general step insights as JSON objects:
|
||||
```json
|
||||
[
|
||||
{{
|
||||
"when_to_use": "General conditions where this pattern is applicable",
|
||||
"experience": "Detailed description of the effective step pattern",
|
||||
"tags": ["general_pattern", "best_practice", "relevant_keywords"],
|
||||
"confidence": 0.6,
|
||||
"step_type": "reasoning|action|observation|decision",
|
||||
"tools_used": ["list", "of", "tools"]
|
||||
}}
|
||||
]
|
||||
```
|
||||
|
||||
step_segmentation_prompt: |
|
||||
You are an expert AI analyst tasked with segmenting a trajectory into meaningful step sequences.
|
||||
|
||||
Your task is to identify natural breakpoints in the execution where one logical unit of work ends and another begins.
|
||||
Consider factors like: task completion, context switches, tool changes, reasoning phases, and logical groupings.
|
||||
|
||||
SEGMENTATION CRITERIA:
|
||||
● LOGICAL COMPLETION: Steps that complete a specific sub-task or reasoning phase
|
||||
● CONTEXT SWITCHES: Points where the agent shifts focus or approach
|
||||
● TOOL BOUNDARIES: Natural breaks around tool usage patterns
|
||||
● REASONING PHASES: Distinct phases of analysis, planning, or execution
|
||||
|
||||
# Original Query
|
||||
{query}
|
||||
|
||||
# Full Trajectory (Total steps: {total_steps})
|
||||
{trajectory_content}
|
||||
|
||||
OUTPUT FORMAT:
|
||||
Provide segmentation points as a JSON array of step indices where splits should occur:
|
||||
```json
|
||||
{{
|
||||
"segment_points": [3, 7, 12, 18],
|
||||
"reasoning": "Brief explanation of segmentation logic"
|
||||
}}
|
||||
```
|
||||
|
||||
Note: Segment points indicate the END of each segment. For example, [3, 7] means:
|
||||
- Segment 1: steps 0-3
|
||||
- Segment 2: steps 4-7
|
||||
- Segment 3: steps 8-end
|
||||
|
||||
experience_validation_prompt: |
|
||||
You are an expert AI analyst tasked with validating the quality and usefulness of extracted step-level experiences.
|
||||
|
||||
Your task is to assess whether the extracted experience is actionable, accurate, and valuable for future agent executions.
|
||||
|
||||
VALIDATION CRITERIA:
|
||||
● ACTIONABILITY: Is the experience specific enough to guide future actions?
|
||||
● ACCURACY: Does the experience correctly reflect the patterns observed?
|
||||
● RELEVANCE: Is the experience applicable to similar future scenarios?
|
||||
● CLARITY: Is the experience clearly articulated and understandable?
|
||||
● UNIQUENESS: Does the experience provide novel insights or common knowledge?
|
||||
|
||||
# Experience to Validate
|
||||
Condition: {condition}
|
||||
Experience Content: {experience_content}
|
||||
|
||||
OUTPUT FORMAT:
|
||||
Provide validation assessment:
|
||||
```json
|
||||
{{
|
||||
"is_valid": true/false,
|
||||
"score": 0.8,
|
||||
"feedback": "Detailed explanation of validation decision",
|
||||
"recommendations": "Suggestions for improvement if applicable"
|
||||
}}
|
||||
```
|
||||
|
||||
Score should be between 0.0 (poor quality) and 1.0 (excellent quality).
|
||||
Mark as invalid if score is below 0.3 or if there are fundamental issues with the experience.
|
||||
|
||||
soft_comparative_step_experience_prompt: |
|
||||
You are an expert AI analyst comparing higher-scoring and lower-scoring step sequences to extract performance insights.
|
||||
|
||||
Your task is to identify the key differences between higher and lower performing approaches at the step level.
|
||||
Focus on what made the higher-scoring approach more effective, even when both approaches may have had partial success.
|
||||
|
||||
SOFT COMPARATIVE ANALYSIS FRAMEWORK:
|
||||
● PERFORMANCE FACTORS: Identify what specifically contributed to the higher score
|
||||
● APPROACH DIFFERENCES: Compare methodologies and execution strategies
|
||||
● EFFICIENCY ANALYSIS: Analyze why one approach was more efficient or effective
|
||||
● OPTIMIZATION INSIGHTS: Extract lessons for improving performance
|
||||
|
||||
EXTRACTION PRINCIPLES:
|
||||
● Focus on INCREMENTAL IMPROVEMENTS and performance optimization
|
||||
● Extract QUALITY INDICATORS that differentiate better vs good approaches
|
||||
● Identify REFINEMENT STRATEGIES that lead to higher scores
|
||||
● Frame insights as PERFORMANCE ENHANCEMENT guidelines
|
||||
|
||||
# Higher-Scoring Step Sequence (Score: {higher_score})
|
||||
{higher_steps}
|
||||
|
||||
# Lower-Scoring Step Sequence (Score: {lower_score})
|
||||
{lower_steps}
|
||||
|
||||
|
||||
OUTPUT FORMAT:
|
||||
Generate 1-2 performance improvement insights as JSON objects:
|
||||
```json
|
||||
[
|
||||
{{
|
||||
"when_to_use": "Specific scenarios where this performance insight applies",
|
||||
"experience": "Detailed analysis of what made the higher-scoring approach more effective",
|
||||
"tags": ["performance_optimization", "score_improvement", "relevant_keywords"],
|
||||
"confidence": 0.7,
|
||||
"step_type": "reasoning|action|observation|decision",
|
||||
"tools_used": ["list", "of", "tools"]
|
||||
}}
|
||||
]
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
import json
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from experiencemaker.enumeration.role import Role
|
||||
from experiencemaker.op import OP_REGISTRY
|
||||
from experiencemaker.op.base_op import BaseOp
|
||||
from experiencemaker.schema.experience import TextExperience, ExperienceMeta
|
||||
from experiencemaker.schema.message import Message, Trajectory
|
||||
from experiencemaker.enumeration.role import Role
|
||||
from experiencemaker.schema.response import SummarizerResponse
|
||||
|
||||
|
||||
@OP_REGISTRY.register()
|
||||
|
|
@ -26,31 +28,27 @@ class SuccessExtractionOp(BaseOp):
|
|||
|
||||
# Use thread pool for parallel processing
|
||||
for trajectory in success_trajectories:
|
||||
if hasattr(trajectory, 'segments') and trajectory.segments:
|
||||
if "segments" in trajectory.metadata:
|
||||
# Process segmented step sequences
|
||||
for segment in trajectory.segments:
|
||||
self.submit_task(self._extract_success_experience_from_steps,
|
||||
steps=segment, trajectory=trajectory)
|
||||
for segment in trajectory.metadata["segments"]:
|
||||
self.submit_task(self._extract_success_experience_from_steps, steps=segment, trajectory=trajectory)
|
||||
else:
|
||||
# Process entire trajectory
|
||||
self.submit_task(self._extract_success_experience_from_steps,
|
||||
steps=trajectory.messages, trajectory=trajectory)
|
||||
self.submit_task(self._extract_success_experience_from_steps,
|
||||
steps=trajectory.messages, trajectory=trajectory)
|
||||
|
||||
# Collect all experiences
|
||||
all_experiences = []
|
||||
for task_result in self.join_task():
|
||||
if task_result:
|
||||
all_experiences.extend(task_result)
|
||||
all_experiences = self.join_task()
|
||||
|
||||
logger.info(f"Extracted {len(all_experiences)} success experiences")
|
||||
|
||||
# Add experiences to context
|
||||
existing_experiences = self.context.get_context("extracted_experiences", [])
|
||||
existing_experiences.extend(all_experiences)
|
||||
self.context.set_context("extracted_experiences", existing_experiences)
|
||||
response: SummarizerResponse = self.context.response
|
||||
response.experience_list.extend(all_experiences)
|
||||
|
||||
def _extract_success_experience_from_steps(self, steps: List[Message], trajectory: Trajectory) -> List[TextExperience]:
|
||||
"""Extract experience from successful step sequences"""
|
||||
# TODO remove try catch
|
||||
try:
|
||||
step_content = self._format_step_sequence(steps)
|
||||
context = self._get_trajectory_context(trajectory, steps)
|
||||
|
|
@ -92,7 +90,7 @@ class SuccessExtractionOp(BaseOp):
|
|||
def _format_step_sequence(self, steps: List[Message]) -> str:
|
||||
"""Format step sequence to string"""
|
||||
step_content_collector = []
|
||||
|
||||
# TODO merge_messages_content
|
||||
for step in steps:
|
||||
step_index = len(step_content_collector)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from typing import List, Dict
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from experiencemaker.op import OP_REGISTRY
|
||||
from experiencemaker.op.base_op import BaseOp
|
||||
from experiencemaker.schema.message import Trajectory
|
||||
|
|
@ -13,25 +15,9 @@ class TrajectoryPreprocessOp(BaseOp):
|
|||
def execute(self):
|
||||
"""Preprocess trajectories: validate and classify"""
|
||||
request: SummarizerRequest = self.context.request
|
||||
if request.traj_list:
|
||||
self.context.set_context("trajectories", request.traj_list)
|
||||
elif request.trajectories:
|
||||
self.context.set_context("trajectories", request.trajectories)
|
||||
else:
|
||||
logger.error("No trajectories is recognized. Please send requests containing traj_list.")
|
||||
|
||||
trajectories: List[Trajectory] = self.context.get_context("trajectories", [])
|
||||
|
||||
if not trajectories:
|
||||
logger.warning("No trajectories found in context")
|
||||
return
|
||||
|
||||
# Validate trajectories
|
||||
valid_trajectories = self._validate_trajectories(trajectories)
|
||||
logger.info(f"Validated {len(valid_trajectories)} out of {len(trajectories)} trajectories")
|
||||
|
||||
# Classify trajectories
|
||||
classified = self._classify_trajectories(valid_trajectories)
|
||||
classified = self._classify_trajectories(request.traj_list)
|
||||
logger.info(f"Classified trajectories - Success: {len(classified['success'])}, "
|
||||
f"Failure: {len(classified['failure'])}, All: {len(classified['all'])}")
|
||||
|
||||
|
|
@ -40,28 +26,6 @@ class TrajectoryPreprocessOp(BaseOp):
|
|||
self.context.set_context("failure_trajectories", classified['failure'])
|
||||
self.context.set_context("all_trajectories", classified['all'])
|
||||
|
||||
def _validate_trajectories(self, trajectories: List[Trajectory]) -> List[Trajectory]:
|
||||
"""Validate trajectory validity"""
|
||||
valid_trajectories = []
|
||||
|
||||
for traj in trajectories:
|
||||
if self._is_valid_trajectory(traj):
|
||||
valid_trajectories.append(traj)
|
||||
else:
|
||||
logger.debug("Invalid trajectory filtered out")
|
||||
|
||||
return valid_trajectories
|
||||
|
||||
def _is_valid_trajectory(self, traj: Trajectory) -> bool:
|
||||
"""Check if trajectory is valid"""
|
||||
if traj is None:
|
||||
return False
|
||||
if not hasattr(traj, 'score') or traj.score is None:
|
||||
return False
|
||||
if not hasattr(traj, 'messages') or not traj.messages or len(traj.messages) == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _classify_trajectories(self, trajectories: List[Trajectory]) -> Dict[str, List[Trajectory]]:
|
||||
"""Classify trajectories based on score threshold"""
|
||||
success_trajectories = []
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import re
|
||||
import json
|
||||
from typing import List, Dict, Any
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from experiencemaker.op import OP_REGISTRY
|
||||
from experiencemaker.op.base_op import BaseOp
|
||||
from experiencemaker.schema.message import Message, Trajectory
|
||||
from experiencemaker.enumeration.role import Role
|
||||
|
||||
|
||||
@OP_REGISTRY.register()
|
||||
|
|
@ -30,15 +31,12 @@ class TrajectorySegmentationOp(BaseOp):
|
|||
# Add segmentation info to trajectories
|
||||
segmented_count = 0
|
||||
for trajectory in target_trajectories:
|
||||
segments = self._segment_trajectory(trajectory)
|
||||
trajectory.segments = segments
|
||||
segments = self._llm_segment_trajectory(trajectory)
|
||||
trajectory.metadata["segments"] = segments
|
||||
segmented_count += 1
|
||||
|
||||
logger.info(f"Segmented {segmented_count} trajectories")
|
||||
|
||||
# Update context with segmented trajectories
|
||||
self.context.set_context("segmented_trajectories", target_trajectories)
|
||||
|
||||
def _get_target_trajectories(self, all_trajectories: List[Trajectory],
|
||||
success_trajectories: List[Trajectory],
|
||||
failure_trajectories: List[Trajectory]) -> List[Trajectory]:
|
||||
|
|
@ -52,55 +50,38 @@ class TrajectorySegmentationOp(BaseOp):
|
|||
else:
|
||||
return all_trajectories
|
||||
|
||||
def _segment_trajectory(self, trajectory: Trajectory) -> List[List[Message]]:
|
||||
"""Segment trajectory into step sequences using LLM"""
|
||||
try:
|
||||
return self._llm_segment_trajectory(trajectory)
|
||||
except Exception as e:
|
||||
logger.error(f"Error segmenting trajectory: {e}")
|
||||
return [trajectory.messages]
|
||||
|
||||
def _llm_segment_trajectory(self, trajectory: Trajectory) -> List[List[Message]]:
|
||||
"""Use LLM for trajectory segmentation"""
|
||||
try:
|
||||
trajectory_content = self._format_trajectory_content(trajectory)
|
||||
trajectory_content = self._format_trajectory_content(trajectory)
|
||||
|
||||
prompt = self.prompt_format(
|
||||
prompt_name="step_segmentation_prompt",
|
||||
query=trajectory.metadata.get('query', ''),
|
||||
trajectory_content=trajectory_content,
|
||||
total_steps=len(trajectory.messages)
|
||||
)
|
||||
prompt = self.prompt_format(
|
||||
prompt_name="step_segmentation_prompt",
|
||||
query=trajectory.metadata.get('query', ''),
|
||||
trajectory_content=trajectory_content,
|
||||
total_steps=len(trajectory.messages)
|
||||
)
|
||||
|
||||
def parse_segmentation(message: Message) -> List[List[Message]]:
|
||||
try:
|
||||
content = message.content
|
||||
segment_points = self._parse_segmentation_response(content)
|
||||
def parse_segmentation(message: Message) -> List[List[Message]]:
|
||||
content = message.content
|
||||
segment_points = self._parse_segmentation_response(content)
|
||||
|
||||
# Segment trajectory based on segmentation points
|
||||
segments = []
|
||||
start_idx = 0
|
||||
# Segment trajectory based on segmentation points
|
||||
segments = []
|
||||
start_idx = 0
|
||||
|
||||
for end_idx in segment_points:
|
||||
if start_idx < end_idx <= len(trajectory.messages):
|
||||
segments.append(trajectory.messages[start_idx:end_idx])
|
||||
start_idx = end_idx
|
||||
for end_idx in segment_points:
|
||||
if start_idx < end_idx <= len(trajectory.messages):
|
||||
segments.append(trajectory.messages[start_idx:end_idx])
|
||||
start_idx = end_idx
|
||||
|
||||
# Add remaining steps
|
||||
if start_idx < len(trajectory.messages):
|
||||
segments.append(trajectory.messages[start_idx:])
|
||||
# Add remaining steps
|
||||
if start_idx < len(trajectory.messages):
|
||||
segments.append(trajectory.messages[start_idx:])
|
||||
|
||||
return segments if segments else [trajectory.messages]
|
||||
return segments if segments else [trajectory.messages]
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error parsing segmentation: {e}")
|
||||
return [trajectory.messages]
|
||||
|
||||
return self.llm.chat(messages=[Message(content=prompt)], callback_fn=parse_segmentation)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"LLM segmentation failed: {e}")
|
||||
return [trajectory.messages]
|
||||
return self.llm.chat(messages=[Message(content=prompt)], callback_fn=parse_segmentation,
|
||||
default_value=[trajectory.messages])
|
||||
|
||||
def _format_trajectory_content(self, trajectory: Trajectory) -> str:
|
||||
"""Format trajectory content for LLM processing"""
|
||||
|
|
|
|||
|
|
@ -5,24 +5,26 @@ from loguru import logger
|
|||
|
||||
from experiencemaker.op import OP_REGISTRY
|
||||
from experiencemaker.op.base_op import BaseOp
|
||||
from experiencemaker.schema.experience import BaseExperience
|
||||
from experiencemaker.schema.request import BaseRequest
|
||||
from experiencemaker.schema.vector_node import VectorNode
|
||||
|
||||
|
||||
@OP_REGISTRY.register()
|
||||
class UpdateVectorStoreOp(BaseOp):
|
||||
INSERT_NODES = "insert_nodes"
|
||||
DELETE_NODE_IDS = "delete_node_ids"
|
||||
INSERT_EXPERIENCE_LIST = "insert_experience_list"
|
||||
DELETE_EXPERIENCE_IDS = "delete_experience_ids"
|
||||
|
||||
def execute(self):
|
||||
request: BaseRequest = self.context.request
|
||||
|
||||
node_ids: List[str] | None = self.context.get_context(self.DELETE_NODE_IDS)
|
||||
if node_ids:
|
||||
self.vector_store.delete(node_ids=node_ids, workspace_id=request.workspace_id)
|
||||
logger.info(f"delete node_ids={json.dumps(node_ids, indent=2)}")
|
||||
experience_ids: List[str] | None = self.context.get_context(self.DELETE_EXPERIENCE_IDS)
|
||||
if experience_ids:
|
||||
self.vector_store.delete(node_ids=experience_ids, workspace_id=request.workspace_id)
|
||||
logger.info(f"delete experience_ids={json.dumps(experience_ids, indent=2)}")
|
||||
|
||||
insert_nodes: List[VectorNode] | None = self.context.get_context(self.INSERT_NODES)
|
||||
if insert_nodes:
|
||||
insert_experience_list: List[BaseExperience] | None = self.context.get_context(self.INSERT_EXPERIENCE_LIST)
|
||||
if insert_experience_list:
|
||||
insert_nodes: List[VectorNode] = [x.to_vector_node() for x in insert_experience_list]
|
||||
self.vector_store.insert(nodes=insert_nodes, workspace_id=request.workspace_id)
|
||||
logger.info(f"insert insert_node.size={len(insert_nodes)}")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue