BechusRantus's picture
Upload folder using huggingface_hub
7134ce7 verified
import re
import torch
import torch.nn.functional as F
from collections import Counter
def key_step_single(content, key_step):
"""
Check if the key steps are present in the content.
"""
if isinstance(key_step, list):
key_step = key_step[0]
# step_texts = re.findall(r"### Step \d+:\s*(.*?)(?=\n###|\Z)", content, re.DOTALL)
step_texts = extract_key_steps(content)
# step_text_combined = " ".join(step_texts).lower()
steps_keywords = key_step.get("Steps", [])
total_keywords = len(steps_keywords)
matched_keywords = 0
for group in steps_keywords:
if isinstance(group, str):
group = [group]
if any(alt.lower() in step_texts for alt in group):
matched_keywords += 1
breakpoint()
reward = matched_keywords / total_keywords if total_keywords > 0 else 0.0
return reward
def extract_key_steps(text):
"""
Extract key steps from the text based on various possible markers.
"""
options = ["Step-by-Step Reasoning:", "**Step-by-Step Reasoning**:", "### Step 1:", "### Step 2:", "### Step 3:", "### Step 4:", "### Step 5:"]
key_steps = ""
for opt in options:
if opt in text:
key_steps = text.split(opt)[-1]
break
return key_steps.strip()
def extract_final_answer(text):
"""
Extract the final answer from the text based on various possible markers.
"""
options = ["The final answer is:", "**Final Answer:**", "**Final Answer**:", "Final Answer", "Answer", "Why take this action?:",
"**Final Answer**", "**Final Decision**:","Final Step:", "<CONCLUSION>"]
final_ans = ""
for opt in options:
if opt in text:
final_ans = text.split(opt)[-1]
break
return final_ans.strip()
def extract_options(text):
"""
Extract options from the text.
"""
pattern = r'([A-F])\)\s*(.+)'
matches = re.findall(pattern, text)
options = [(label, option) for label, option in matches]
if not options:
if "none of the " in text.lower():
return [('F', 'None of the option.')]
return [('none','none')]
return options
def description_accuracy_reward(completions, solution, key_steps, **kwargs):
"""Reward function that checks if the completion contains key phrases."""
contents = [completion for completion in completions]
rewards = []
# Extract keywords from solution
sol_final_answer = extract_final_answer(solution[0])
keywords = ["ego vehicle", "car directly ahead", "distance management", "barrier", "restricted access", "pedestrian", "safety", "navigation", "path", "caution", "speed"]
for content in contents:
reward = 0.0
student_final_answer = extract_final_answer(content)
# Check for presence of keywords
matched_keywords = [word for word in keywords if word in student_final_answer.lower()]
reward = len(matched_keywords) / len(keywords) if keywords else 0.0
rewards.append(reward)
return rewards
def description_accuracy_rewardV2(completions, solution, key_steps, **kwargs):
"""Reward function that checks if the completion contains key phrases and key steps."""
contents = [completion for completion in completions]
rewards = []
# Extract keywords from solution
sol_final_answer = extract_final_answer(solution[0])
keywords = ["ego vehicle", "car directly ahead", "distance management", "barrier", "restricted access", "pedestrian", "safety", "navigation", "path", "caution", "speed"]
for content in contents:
reward = 0.0
student_final_answer = extract_final_answer(content)
# Check for presence of keywords
matched_keywords = [word for word in keywords if word in student_final_answer.lower()]
keyword_reward = len(matched_keywords) / len(keywords) if keywords else 0.0
# Check for key steps
if key_steps:
step_reward = key_step_single(content, key_steps)
reward = 0.5 * keyword_reward + 0.5 * step_reward
else:
reward = keyword_reward
rewards.append(reward)
return rewards
def process_text_embed(model, tokenizer, sentence):
# model_path = "/high_perf_store/mlinfra-vepfs/qiankangan/DriveLMM-o1-main/all-MiniLM-L6-v2" # 确保这是模型文件夹的绝对路径
# model = SentenceTransformer(model_path)
#Mean Pooling - Take attention mask into account for correct averaging
def mean_pooling(model_output, attention_mask):
token_embeddings = model_output[0] #First element of model_output contains all token embeddings
input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
return torch.sum(token_embeddings * input_mask_expanded, 1) / torch.clamp(input_mask_expanded.sum(1), min=1e-9)
# Sentences we want sentence embeddings for
# sentences = ['This is an example sentence', 'Each sentence is converted']
# Tokenize sentences
encoded_input = tokenizer(sentence, padding=True, truncation=True, return_tensors='pt')
# breakpoint()
# Compute token embeddings
with torch.no_grad():
model_output = model(**encoded_input)
# breakpoint()
# Perform pooling
sentence_embeddings = mean_pooling(model_output, encoded_input['attention_mask'])
# Normalize embeddings
sentence_embeddings = F.normalize(sentence_embeddings, p=2, dim=1)
return sentence_embeddings
def description_semantic_reward(completions, solution, key_steps, **kwargs):
from sentence_transformers import SentenceTransformer, util
from transformers import AutoTokenizer, AutoModel
tokenizer = AutoTokenizer.from_pretrained('all-MiniLM-L6-v2')
model = AutoModel.from_pretrained('all-MiniLM-L6-v2')
"""Reward function that uses semantic similarity to evaluate the answer."""
contents = [completion for completion in completions]
rewards = []
# Encode the solution
sol_final_answer = extract_final_answer(solution[0])
solution_embedding = process_text_embed(model, tokenizer, [sol_final_answer])
for content in contents:
reward = 0.0
student_final_answer = extract_final_answer(content)
# Encode the student answer
student_embedding = process_text_embed(model, tokenizer, [student_final_answer])
# Calculate cosine similarity
breakpoint()
similarity = util.cos_sim(solution_embedding, student_embedding)
reward = float(similarity)
breakpoint()
rewards.append(reward)
return rewards
def mc_accuracy_reward(completions, solution, **kwargs):
"""Reward function that checks if the completion is correct for multiple-choice questions."""
contents = [completion for completion in completions]
rewards = []
# Extract correct answer from solution
sol_options = extract_options(solution[0])
breakpoint()
sol_correct_label = None
for label, option in sol_options:
if "correct" in option.lower() or "answer" in option.lower():
sol_correct_label = label
break
if not sol_correct_label:
sol_final_answer = extract_final_answer(solution[0])
sol_correct_label_match = re.search(r'([A-F])', sol_final_answer)
sol_correct_label = sol_correct_label_match.group(1) if sol_correct_label_match else None
breakpoint()
for content in contents:
reward = 0.0
# Extract student's answer
student_final_answer = extract_final_answer(content)
student_label_match = re.search(r'([A-F])', student_final_answer)
student_label = student_label_match.group(1) if student_label_match else None
# Compare labels
if student_label and sol_correct_label and student_label == sol_correct_label:
reward = 1.0
rewards.append(reward)
breakpoint()
return rewards
def check_reasoning_completeness(text):
"""
Check if the text contains all required sections.
"""
required_sections = [
"Step-by-Step Reasoning",
"Final Answer"
]
# breakpoint()
missing_sections = [section for section in required_sections if section not in text]
# breakpoint()
return not missing_sections
def check_reasoning_logic(text):
"""
Check if the sections appear in the correct order by finding their positions.
"""
# Find the start and end positions of '**Step-by-Step Reasoning**' section
reasoning_steps_start = text.find("**Step-by-Step Reasoning**")
if reasoning_steps_start == -1:
return False # '**Reasoning Steps**' not found
reasoning_steps_end = text.find("**Final Answer**", reasoning_steps_start)
if reasoning_steps_end == -1:
return False # '**Final Answer**' not found after '**Reasoning Steps**'
# Find the start position of '**Final Answer**' section
final_answer_start = text.find("**Final Answer**")
if final_answer_start == -1 or final_answer_start < reasoning_steps_start:
return False # '**Final Answer**' not found or not after '**Reasoning Steps**'
# Check if there is content between '**Reasoning Steps**' and '**Final Answer**'
reasoning_content = text[reasoning_steps_start:final_answer_start].strip()
if not reasoning_content:
return False # No content in '**Reasoning Steps**' section
# Check if there is content after '**Final Answer**'
final_answer_content = text[final_answer_start:].strip()
if not final_answer_content:
return False # No content in '**Final Answer**' section
return True
def description_validity_reward(completions, **kwargs):
"""Reward function that checks if the completion has a specific format."""
# Check if answer format is correct
pattern = r"\*\*Step-by-Step Reasoning\*\*:\n\n(\d+\. .+\n\n)+\*\*Final Answer\*\*: .+"
completion_contents = [completion for completion in completions]
matches = [re.fullmatch(pattern, content, re.DOTALL) for content in completion_contents]
# Check if the content includes all required sections and in correct order
validity_rewards = []
for content in completion_contents:
if not check_reasoning_completeness(content):
validity_rewards.append(0.0)
continue
if not check_reasoning_logic(content):
validity_rewards.append(0.0)
continue
validity_rewards.append(1.0)
breakpoint()
# Combine format and validity rewards
rewards = []
for format_match, validity in zip(matches, validity_rewards):
if format_match:
rewards.append(0.5 + validity * 0.5) # 0.5 for format, 0.5 for validity
else:
rewards.append(validity) # Only validity reward if format is incorrect
breakpoint()
return rewards
if __name__ == "__main__":
"""debug description"""
solution = ["**Step-by-Step Reasoning**:\n\n1. In the top middle image, the ego vehicle is right behind another vehicle. This car is directly in its path and needs to be considered for speed and distance management.\n2. The top middle image also shows a barrier ahead. This indicates restricted access which the ego vehicle must consider before proceeding.\n3. The top right image includes a person standing near the road. The ego vehicle should be cautious of pedestrians and maintain a safe distance. \n\n**Final Answer**: The three most important objects the ego vehicle must consider are the car directly ahead, the barrier indicating restricted access, and the pedestrian standing on the side of the road. These objects are crucial for safety and navigation."]
completion = ["**Step-by-Step Reasoning**:\n\n1. In the 'front' image, there is a car directly ahead of the ego vehicle. This is crucial for the ego vehicle to consider due to potential obstacles or traffic flow.\n\n2. In the 'front right' image, there are pedestrians visible on the pathway. The presence of pedestrians is significant as they may cross the path of the ego vehicle or be influenced its movement.\n\n3. In the 'back right' image, there is another vehicle approaching from the opposite direction. This vehicle is important for the ego vehicle to monitor to avoid collisions and ensure safe passage.\n\n**Final Answer**: The three most important objects in the scene are:\n1. The car directly in front of the ego vehicle in the 'front' image.\n2. The pedestrians on the sidewalk in the 'front right' image.\n3. The approaching vehicle in the 'back right' image."]
key_steps = [
{
"Steps": [
["car", "directly ahead"],
["barrier", "ahead", "restricted access"],
["person", "near road", " pedestrians"]
]
}
]
description_validity_reward(completion)
# description_accuracy_rewardV2(completions=completion, solution=solution, key_steps=key_steps)
# description_semantic_reward(completions=completion, solution=solution, key_steps=key_steps)
"""debug mc"""
# solution = ["**Step-by-Step Reasoning**:\n\n1. In the \"front\" image of the top row, there is a black car ahead, in a lane that is narrowed by a divider. This suggests limited space for maneuvering.\n2. In the \"back\" image of the bottom row, the car is in a lane that has space on the left, but the right side is blocked by another car.\n3. Considering the options, \"Change lane to right\" (D) is not feasible due to the blockage. \"Come to a complete stop\" (A) or \"Brake suddenly\" (B) might not ensure collision avoidance given the proximity of the car ahead.\n4. \"Speed up\" (C) is not ideal in a potentially congested area. The safest way could be to \"Change lane to left\" (E) since it appears more space is available.\n\n**Final Answer**: E) Change lane to left."]
# completion = ["**Step-by-Step Reasoning**:\n\n1. In the 'front' image, there's a car directly ahead of the ego vehicle, which indicates potential for collision if movement continues.\n2. The current speed of the ego vehicle is very low at 0.82 km/h, suggesting that stopping would be effective without skidding or abrupt maneuvers.\n3. There are no visible obstacles or safe lanes to the left or right that are clear for immediate lane changes.\n4. Given the proximity to the car ahead and lack of safe maneuver spaces, continuing forward is unsafe.\n\n**Final Answer**: A) Come to a complete stop."]
# completion = ["**Step-by-Step Reasoning**:\n\n1. In the 'front' image, there's a car directly ahead of the ego vehicle, which indicates potential for collision if movement continues.\n2. The current speed of the ego vehicle is very low at 0.82 km/h, suggesting that stopping would be effective without skidding or abrupt maneuvers.\n3. There are no visible obstacles or safe lanes to the left or right that are clear for immediate lane changes.\n4. Given the proximity to the car ahead and lack of safe maneuver spaces, continuing forward is unsafe.\n\n**Final Answer**: E) Change lane to left."]
# mc_accuracy_reward(completions=completion, solution=solution)