Setting the file. One moment.
Rlvr Reward Function Source Template · AWS AI ML · aws/agent-toolkit-for-aws · Skills Docs
Issue No. 14 · AWS AI ML
↖ Back to the coverMessaging And Streaming Skills
Migration And Modernization Skills
Networking And Content Delivery Skills
Security And Identity Skills
Web And Mobile Development
120 chapters · 648 min
Rlvr Reward Function Source Template ContentsBack to the top of the page 10
Setup DevOps Agent
24.7
Code Output Guide · references
RDS Oracle
references/finetuning/templates/rlvr_reward_function_source_template.py
references/finetuning/templates/ rlvr_reward_function_source_template.py
Python · 251 lines · 9 KB
# Add any other imports your use case requires
14
15 # ========================================================================================
16 # NOTE : INITIAL SUGGESTION ONLY - MUST BE CUSTOMIZED
17 #
18 # YOU MUST:
19 # 1. Review and update each section per YOUR use case
20 # 2. Customize the logic for YOUR SPECIFIC requirements
21 # 3. Replace example values (field names, thresholds, etc.) with your actual values
22 # 4. Test thoroughly before using
23 #
24 # DO NOT use this code as-is. It will not work until you uncomment and customize it.
25 # =========================================================================================
26
27
28 # =========================================================================================
29 # SECTION 1: Helper function 1
30 # =========================================================================================
31 # TODO : UPDATE or REMOVE the helper function as per YOUR use case
32 # Note the below lines of code are examples and will not work for your use case
33 # You MUST update them to match YOUR use case
34 def extract_number (text: str ) -> Optional[ float ]:
35 """
36 Extract numerical answer from text.
37 Looks for numbers after answer keywords, or returns the last number found.
38
39 Args:
40 text: Text containing a numerical answer
41
42 Returns:
43 Extracted number as float, or None if no number found
44 """
45 if not text:
46 return None
47
48 # Try to find numbers after common answer keywords
49 answer_patterns = [
50 r " (?: equals | is | answer is | result is | = )\s * ( - ? \d + \. ? \d * ) " ,
51 r " (?: answer | result | solution ) : \s * ( - ? \d + \. ? \d * ) " ,
52 ]
53
54 for pattern in answer_patterns:
55 match = re.search(pattern, text, re. IGNORECASE )
56 if match:
57 try :
58 return float (match.group( 1 ))
59 except ValueError :
60 pass
61
62 # Fallback: find all numbers and return the last one (likely the answer)
63 pattern = r "- ? \d + \. ? \d * "
64 matches = re.findall(pattern, text)
65
66 if matches:
67 try :
68 return float (matches[ - 1 ]) # Return last number instead of first
69 except ValueError :
70 return None
71
72 return None
73
74
75 # =========================================================================================
76 # SECTION 2: Helper function 2
77 # =========================================================================================
78 # TODO : UPDATE or REMOVE the helper function as per YOUR use case
79 # Note the below lines of code are examples and will not work for your use case
80 # You MUST update them to match YOUR use case
81 def compute_reasoning_quality (response: str ) -> float :
82 """
83 Compute reasoning quality score based on response characteristics.
84 This is a simple heuristic - customize based on your needs.
85
86 Args:
87 response: The model's response text
88
89 Returns:
90 Quality score between 0.0 and 1.0
91 """
92 if not response:
93 return 0.0
94
95 score = 0.0
96
97 # Check for reasoning indicators (customize these for your use case)
98 reasoning_indicators = [
99 "because" ,
100 "therefore" ,
101 "thus" ,
102 "since" ,
103 "so" ,
104 "first" ,
105 "second" ,
106 "then" ,
107 "finally" ,
108 "step" ,
109 "calculate" ,
110 "compute" ,
111 "equals" ,
112 ]
113
114 response_lower = response.lower()
115
116 # Award points for reasoning indicators (max 0.55)
117 indicator_count = sum ( 1 for indicator in reasoning_indicators if indicator in response_lower)
118 score += min (indicator_count * 0.11 , 0.55 )
119
120 # Award points for response length (indicates detailed reasoning, max 0.25)
121 if len (response) > 30 :
122 score += 0.05
123 if len (response) > 60 :
124 score += 0.1
125 if len (response) > 120 :
126 score += 0.1
127
128 # Award points for structured response (max 0.2)
129 if " \n " in response or "." in response:
130 score += 0.2
131
132 return min (score, 1.0 )
133
134
135 # =========================================================================================
136 # SECTION 3: Sample reward function
137 # =========================================================================================
138 # TODO : UPDATE or REMOVE the reward function as per YOUR use case
139 # Note the below lines of code are examples and will not work for your use case
140 # You MUST update them to match YOUR use case
141 def reward_function (sample: Dict[ str , Any], index: int ) -> Dict[ str , Any]:
142 """
143 Args:
144 sample: Dictionary containing messages and reference_answer
145 index: Sample index in batch
146
147 Returns:
148 Dictionary with reward scores and metrics
149 """
150 # ========================================================================
151 # SECTION 4: Parse input
152 # ========================================================================
153 # TODO : UPDATE logic to parse the input as per YOUR use case
154 # Note the below lines of code are examples and will not work for your use case
155 # You MUST update them to match YOUR use case
156 # Extract the response and reference
157 messages = sample.get( "messages" , sample.get( "prompt" , []))
158 reference_answer = sample.get( "reference_answer" , {}).get( "text" , "" ) or sample.get(
159 "reward_model" , {}
160 ).get( "ground_truth" , "" )
161
162 # Get the question and assistant's response
163 question = ""
164 response = ""
165 for msg in messages:
166 if msg.get( "role" ) == "user" :
167 question = msg.get( "content" , "" )
168 elif msg.get( "role" ) == "assistant" :
169 response = msg.get( "content" , "" )
170
171 # Extract numerical answers
172 predicted = extract_number(response)
173 expected = extract_number(reference_answer)
174
175 # Compute metrics
176 exact_match = 0.0
177 answer_present = 0.0
178 reasoning_quality = compute_reasoning_quality(response)
179
180 if predicted is not None and expected is not None :
181 exact_match = 1.0 if abs (predicted - expected) < 1e-6 else 0.0
182 answer_present = 1.0
183
184 # ========================================================================
185 # SECTION 5: Compute reward scores
186 # ========================================================================
187 # TODO : UPDATE logic to compute aggregate score
188 # Note the below lines of code are examples and will not work for your use case
189 # You MUST update them to match YOUR use case
190 # Aggregate reward computation
191 aggregate_reward = 0.7 * exact_match + 0.3 * reasoning_quality
192
193 # ========================================================================
194 # SECTION 6: Form the metrics list
195 # ========================================================================
196 # TODO : UPDATE logic to compute metrics list
197 # Note the below lines of code are examples and will not work for your use case
198 # You MUST update them to match YOUR use case
199 metrics = [
200 { "name" : "exact_match" , "value" : float (exact_match), "type" : "Reward" },
201 { "name" : "answer_present" , "value" : float (answer_present), "type" : "Metric" },
202 { "name" : "reasoning_quality" , "value" : float (reasoning_quality), "type" : "Metric" },
203 ]
204
205 # ========================================================================
206 # SECTION 7: Return output
207 # ========================================================================
208 # TODO : UPDATE the return statement to return YOUR outout
209 # UPDATE the key before creating the evaluator
210 # Note the below lines of code are examples and will not work for your use case
211 # You MUST update them to match YOUR use case
212
213 return {
214 "id" : str (sample.get( "my_key" , f "sample- { index :03d} " )), # Use formatted index as fallback
215 "aggregate_reward_score" : float (aggregate_reward),
216 "metrics_list" : metrics,
217 }
218
219
220 def lambda_handler (event: Dict[ str , Any], context: Any) -> Dict[ str , Any]:
221 """
222 AWS Lambda Handler for reward function
223 """
224 try :
225 # Extract batch from event
226 batch = event.get( "input" , event) if isinstance (event, dict ) else event
227 if "batch" in event:
228 batch = event.get( "batch" , [])
229 elif "body" in event:
230 body = json.loads(event.get( "body" , " {} " ))
231 batch = body.get( "batch" , [])
232
233 if not batch:
234 return { "error" : "Missing or empty batch" }
235
236 # Process each sample
237 results = []
238 for i, sample in enumerate (batch):
239 try :
240 result = reward_function(sample, i)
241 results.append(result)
242 except Exception as e:
243 return { "error" : str (e)}
244
245 return {
246 "statusCode" : 200 ,
247 "headers" : { "Content-Type" : "application/json" },
248 "body" : json.dumps(results),
249 }
250 except Exception as e:
251 return { "statusCode" : 400 , "body" : json.dumps({ "error" : str (e)})}