Spaces:
Sleeping
Sleeping
Commit
·
1ed0430
1
Parent(s):
7122f32
Remover camada de guardrail de validacao de input
Browse files- app.py +2 -36
- gensim/utils.py +0 -92
app.py
CHANGED
|
@@ -22,7 +22,7 @@ from gensim.agent import Agent
|
|
| 22 |
from gensim.critic import Critic
|
| 23 |
from gensim.sim_runner import SimulationRunner
|
| 24 |
from gensim.memory import Memory
|
| 25 |
-
from gensim.utils import set_gpt_model, clear_messages, translate_natural_language_to_task_name
|
| 26 |
|
| 27 |
|
| 28 |
class DemoRunner:
|
|
@@ -71,20 +71,6 @@ class DemoRunner:
|
|
| 71 |
print("cfg = ", cfg)
|
| 72 |
memory = Memory(cfg)
|
| 73 |
|
| 74 |
-
# Validar input do usuário com guardrail LLM
|
| 75 |
-
if target_task_name and target_task_name.strip():
|
| 76 |
-
print(f"Validando input do usuário: '{target_task_name}'...")
|
| 77 |
-
is_valid, feedback, suggested_alternative = validate_task_input_with_llm(
|
| 78 |
-
target_task_name,
|
| 79 |
-
interaction_txt=memory.chat_log
|
| 80 |
-
)
|
| 81 |
-
|
| 82 |
-
if not is_valid:
|
| 83 |
-
error_msg = f"⚠️ Tarefa não é viável no simulador.\n\n{feedback}"
|
| 84 |
-
if suggested_alternative:
|
| 85 |
-
error_msg += f"\n\n💡 Sugestão: {suggested_alternative}"
|
| 86 |
-
return error_msg, None
|
| 87 |
-
|
| 88 |
# Detectar se é linguagem natural e traduzir se necessário
|
| 89 |
if target_task_name and (' ' in target_task_name or any(c.isupper() for c in target_task_name) or not target_task_name.replace('-', '').replace('_', '').isalnum()):
|
| 90 |
print(f"Detectado linguagem natural: '{target_task_name}' - traduzindo...")
|
|
@@ -104,21 +90,6 @@ class DemoRunner:
|
|
| 104 |
def run(self, instruction, progress):
|
| 105 |
cfg = self._cfg
|
| 106 |
|
| 107 |
-
# Validar input do usuário com guardrail LLM
|
| 108 |
-
if instruction and instruction.strip():
|
| 109 |
-
print(f"Validando input do usuário: '{instruction}'...")
|
| 110 |
-
is_valid, feedback, suggested_alternative = validate_task_input_with_llm(
|
| 111 |
-
instruction,
|
| 112 |
-
interaction_txt=self.simulation_runner.chat_log
|
| 113 |
-
)
|
| 114 |
-
|
| 115 |
-
if not is_valid:
|
| 116 |
-
error_msg = f"⚠️ Tarefa não é viável no simulador.\n\n{feedback}"
|
| 117 |
-
if suggested_alternative:
|
| 118 |
-
error_msg += f"\n\n💡 Sugestão: {suggested_alternative}"
|
| 119 |
-
yield f"Validação falhou: {error_msg}", error_msg, None, None
|
| 120 |
-
return
|
| 121 |
-
|
| 122 |
# Detectar se é linguagem natural e traduzir se necessário
|
| 123 |
if instruction and (' ' in instruction or any(c.isupper() for c in instruction) or not instruction.replace('-', '').replace('_', '').isalnum()):
|
| 124 |
print(f"Detectado linguagem natural: '{instruction}' - traduzindo...")
|
|
@@ -165,12 +136,7 @@ def setup(api_key, option_choice, model_choice, target_task_name):
|
|
| 165 |
demo_runner = DemoRunner()
|
| 166 |
|
| 167 |
if option_choice == 'top-down':
|
| 168 |
-
|
| 169 |
-
# Se retornou tupla (erro, None), retornar diretamente
|
| 170 |
-
if isinstance(result, tuple) and len(result) == 2 and result[1] is None:
|
| 171 |
-
return result
|
| 172 |
-
# Caso contrário, é string de sucesso, concatenar com option_choice
|
| 173 |
-
info = result + option_choice
|
| 174 |
# elif option_choice == 'bottom-up':
|
| 175 |
# info = demo_runner.setup(api_key, model_choice) + option_choice
|
| 176 |
else:
|
|
|
|
| 22 |
from gensim.critic import Critic
|
| 23 |
from gensim.sim_runner import SimulationRunner
|
| 24 |
from gensim.memory import Memory
|
| 25 |
+
from gensim.utils import set_gpt_model, clear_messages, translate_natural_language_to_task_name
|
| 26 |
|
| 27 |
|
| 28 |
class DemoRunner:
|
|
|
|
| 71 |
print("cfg = ", cfg)
|
| 72 |
memory = Memory(cfg)
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
# Detectar se é linguagem natural e traduzir se necessário
|
| 75 |
if target_task_name and (' ' in target_task_name or any(c.isupper() for c in target_task_name) or not target_task_name.replace('-', '').replace('_', '').isalnum()):
|
| 76 |
print(f"Detectado linguagem natural: '{target_task_name}' - traduzindo...")
|
|
|
|
| 90 |
def run(self, instruction, progress):
|
| 91 |
cfg = self._cfg
|
| 92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
# Detectar se é linguagem natural e traduzir se necessário
|
| 94 |
if instruction and (' ' in instruction or any(c.isupper() for c in instruction) or not instruction.replace('-', '').replace('_', '').isalnum()):
|
| 95 |
print(f"Detectado linguagem natural: '{instruction}' - traduzindo...")
|
|
|
|
| 136 |
demo_runner = DemoRunner()
|
| 137 |
|
| 138 |
if option_choice == 'top-down':
|
| 139 |
+
info = demo_runner.setup_top_down(api_key, target_task_name, model_choice) + option_choice
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
# elif option_choice == 'bottom-up':
|
| 141 |
# info = demo_runner.setup(api_key, model_choice) + option_choice
|
| 142 |
else:
|
gensim/utils.py
CHANGED
|
@@ -391,98 +391,6 @@ Return ONLY the task name in the format "word-word-word", nothing else. No expla
|
|
| 391 |
return fallback
|
| 392 |
|
| 393 |
|
| 394 |
-
def validate_task_input_with_llm(user_input, interaction_txt=None):
|
| 395 |
-
"""
|
| 396 |
-
Valida o input do usuário usando LLM para verificar se a tarefa é viável
|
| 397 |
-
dentro das limitações do simulador e do framework.
|
| 398 |
-
|
| 399 |
-
Returns:
|
| 400 |
-
(is_valid: bool, feedback: str, suggested_alternative: str)
|
| 401 |
-
"""
|
| 402 |
-
prompt = f"""You are a validation system for a robotic simulation framework. Your job is to check if a user's task request is feasible within the system's limitations.
|
| 403 |
-
|
| 404 |
-
SYSTEM LIMITATIONS:
|
| 405 |
-
1. **Language Support**: The system accepts input in ANY language (Portuguese, English, Spanish, etc.). The input will be automatically translated to the task format. DO NOT reject tasks based on language.
|
| 406 |
-
2. **Available Primitives**: Only PickPlace (pick and place) and Push are available. No cutting, breaking, throwing, or destructive actions.
|
| 407 |
-
3. **Available Assets**: Only these assets exist:
|
| 408 |
-
- stacking/block.urdf (blocks)
|
| 409 |
-
- stacking/ball.urdf (balls/spheres)
|
| 410 |
-
- stacking/stand.urdf (stands/bases)
|
| 411 |
-
- container/container-template.urdf (containers)
|
| 412 |
-
- bowl/bowl.urdf (bowls)
|
| 413 |
-
- zone/zone.urdf (zones)
|
| 414 |
-
- corner/corner-template.urdf (corners)
|
| 415 |
-
- cylinder/cylinder-template.urdf (cylinders)
|
| 416 |
-
- box/box-template.urdf (boxes)
|
| 417 |
-
- pallet/pallet.urdf (pallets)
|
| 418 |
-
- No custom assets can be created
|
| 419 |
-
4. **Workspace Bounds**: All objects must be within X: [0.25, 0.75], Y: [-0.5, 0.5], Z: [0, 0.3]
|
| 420 |
-
5. **Object Limits**: Recommended 5-20 objects per task. More than 30-50 objects may cause performance issues.
|
| 421 |
-
6. **Unsupported Actions**:
|
| 422 |
-
- "Knock down" or "destroy" structures (can use "place near" or "push near" instead)
|
| 423 |
-
- Cutting, breaking, or modifying objects
|
| 424 |
-
- Throwing objects
|
| 425 |
-
- Complex physics interactions beyond pick-place-push
|
| 426 |
-
- Tasks requiring more than 25-30 steps
|
| 427 |
-
7. **Available Colors**: red, blue, green, yellow, orange, purple, brown (no custom colors)
|
| 428 |
-
8. **No Dynamic Object Creation**: All objects must be created at task initialization
|
| 429 |
-
|
| 430 |
-
USER INPUT: "{user_input}"
|
| 431 |
-
|
| 432 |
-
Analyze this task request and respond in the following JSON format:
|
| 433 |
-
{{
|
| 434 |
-
"is_valid": true/false,
|
| 435 |
-
"reason": "brief explanation of why it's valid or invalid",
|
| 436 |
-
"violations": ["list of specific limitations violated, if any"],
|
| 437 |
-
"suggested_alternative": "suggested alternative task description if invalid, or empty string if valid"
|
| 438 |
-
}}
|
| 439 |
-
|
| 440 |
-
Respond ONLY with valid JSON, no other text."""
|
| 441 |
-
|
| 442 |
-
try:
|
| 443 |
-
result = generate_feedback(
|
| 444 |
-
prompt,
|
| 445 |
-
max_tokens=300,
|
| 446 |
-
temperature=0.0,
|
| 447 |
-
interaction_txt=interaction_txt,
|
| 448 |
-
retry_max=3
|
| 449 |
-
)
|
| 450 |
-
|
| 451 |
-
# Limpar o resultado
|
| 452 |
-
result = result.strip()
|
| 453 |
-
result = re.sub(r'```json\s*', '', result)
|
| 454 |
-
result = re.sub(r'```\s*', '', result).strip()
|
| 455 |
-
|
| 456 |
-
# Tentar parsear JSON
|
| 457 |
-
validation_result = json.loads(result)
|
| 458 |
-
|
| 459 |
-
is_valid = validation_result.get('is_valid', False)
|
| 460 |
-
reason = validation_result.get('reason', 'No reason provided')
|
| 461 |
-
violations = validation_result.get('violations', [])
|
| 462 |
-
suggested_alternative = validation_result.get('suggested_alternative', '')
|
| 463 |
-
|
| 464 |
-
# Construir feedback detalhado
|
| 465 |
-
feedback = reason
|
| 466 |
-
if violations:
|
| 467 |
-
feedback += "\n\nLimitações violadas:\n" + "\n".join(f"- {v}" for v in violations)
|
| 468 |
-
|
| 469 |
-
if interaction_txt is not None:
|
| 470 |
-
status = "VALID" if is_valid else "INVALID"
|
| 471 |
-
add_to_txt(interaction_txt, f"Input validation ({status}): {reason}", with_print=True)
|
| 472 |
-
|
| 473 |
-
return is_valid, feedback, suggested_alternative
|
| 474 |
-
|
| 475 |
-
except json.JSONDecodeError as e:
|
| 476 |
-
print(f"Error parsing validation JSON: {e}")
|
| 477 |
-
print(f"Raw response: {result}")
|
| 478 |
-
# Fallback: assumir válido se não conseguir parsear
|
| 479 |
-
return True, "Validação não pôde ser processada, prosseguindo...", ""
|
| 480 |
-
except Exception as e:
|
| 481 |
-
print(f"Error in task validation: {e}")
|
| 482 |
-
# Fallback: assumir válido em caso de erro
|
| 483 |
-
return True, f"Erro na validação: {str(e)}. Prosseguindo...", ""
|
| 484 |
-
|
| 485 |
-
|
| 486 |
def format_finetune_prompt(task_name):
|
| 487 |
instruction_text = open('prompts/finetune_instructions_prompt.txt').read()
|
| 488 |
instruction_text = instruction_text.replace("TASK_NAME_TEMPLATE", task_name)
|
|
|
|
| 391 |
return fallback
|
| 392 |
|
| 393 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 394 |
def format_finetune_prompt(task_name):
|
| 395 |
instruction_text = open('prompts/finetune_instructions_prompt.txt').read()
|
| 396 |
instruction_text = instruction_text.replace("TASK_NAME_TEMPLATE", task_name)
|