2525- google/gemma-3-4b-it
2626- google/gemma-3-1b-it
2727
28- Gemma 2 family:
29- - google/gemma-2-27b-it
30- - google/gemma-2-9b-it
31-
3228OpenAI open weights family:
3329- openai/gpt-oss-120b
3430- openai/gpt-oss-20b
3834import concurrent .futures
3935import os
4036import random
37+ import re
4138import time
4239
4340from absl import logging
6259
6360_MAX_ALLOWED_TOKENS_DEFAULT = int (1e5 )
6461
65- # The following parameter is specific to Gemma2, not needed for other models.
66- # Max tokens for Gemma2 is really 8193, but we leave substantial margin since
67- # estimates of the number of tokens are imprecise and also calculated before
68- # adding the system messages.
69- _MAX_ALLOWED_TOKENS_GEMMA2 = 7000
70-
7162# Override max allowed tokens for specific models here.
72- _MAX_ALLOWED_TOKENS_OVERRIDES = {
73- 'google/gemma-2-27b-it' : _MAX_ALLOWED_TOKENS_GEMMA2 ,
74- 'google/gemma-2-9b-it' : _MAX_ALLOWED_TOKENS_GEMMA2 ,
75- }
63+ _MAX_ALLOWED_TOKENS_OVERRIDES = {}
7664
7765
78- def _find_response_start_index ( tokens ):
79- r """Finds the start of the response in the prompt .
66+ def _find_concatenated_subsequence ( source : list [ str ], target : str ):
67+ """Get start idx in source where adjacent elements concatenated equal target .
8068
8169 Args:
82- tokens: A list of strings.
70+ source: List of strings
71+ target: String to find
8372
8473 Returns:
85- The index of the last occurrence of '<start_of_turn>' followed by 'model'
86- and '\n', or 1 if the sequence is not found. This corresponds to the start
87- of the response.
74+ int: Starting idx in source where the subsequence begins, or -1 if not found
8875 """
89- assert len (tokens ) >= 3 , "Response doesn't match expectation."
90- for i in range (len (tokens ) - 3 , - 1 , - 1 ):
91- if (
92- tokens [i ] == '<start_of_turn>'
93- and tokens [i + 1 ] == 'model'
94- and tokens [i + 2 ] == '\n '
95- ):
96- return i + 3 # Return the index after the sequence
97- raise ValueError ("Response doesn't match expectation." )
76+ # Remove spaces.
77+ target = re .sub (r'[\s\u2581]+' , '' , target )
78+
79+ if not target : # Empty target
80+ return 0 if source else - 1
81+
82+ for i in range (len (source )):
83+ concatenated = ''
84+ for j in range (i , len (source )):
85+ # Remove spaces.
86+ concatenated += re .sub (r'[\s\u2581]+' , '' , source [j ])
87+ if concatenated == target :
88+ return i
89+ if concatenated not in target :
90+ break
91+ # Early termination if we've already exceeded the target length
92+ if len (concatenated ) > len (target ):
93+ break
94+
95+ return - 1 # Not found
9896
9997
10098def _ensure_prompt_not_too_long (
@@ -134,8 +132,8 @@ def _ensure_prompt_not_too_long(
134132 return new_prompt
135133
136134
137- class Default (language_model .LanguageModel ):
138- """Language Model that uses Together AI models."""
135+ class DefaultCompletion (language_model .LanguageModel ):
136+ """Language Model that uses Together AI models in `completion` mode ."""
139137
140138 def __init__ (
141139 self ,
@@ -185,9 +183,8 @@ def sample_text(
185183 {
186184 'role' : 'system' ,
187185 'content' : (
188- 'You always continue sentences provided '
189- 'by the user and you never repeat what '
190- 'the user has already said. All responses must end with a '
186+ 'You are an autoregressive LLM. You always complete user '
187+ 'inputs. All responses must end with a '
191188 'period. Try not to use lists, but if you must, then '
192189 'always delimit list items using either '
193190 r"semicolons or single newline characters ('\n'), never "
@@ -286,37 +283,13 @@ def _sample_choice(
286283 )
287284 time .sleep (seconds_to_sleep )
288285 try :
289- messages = [
290- {
291- 'role' : 'system' ,
292- 'content' : (
293- 'You always continue sentences provided '
294- + 'by the user and you never repeat what '
295- + 'the user already said.'
296- ),
297- },
298- {
299- 'role' : 'user' ,
300- 'content' : 'Question: Is Jake a turtle?\n Answer: Jake is ' ,
301- },
302- {'role' : 'assistant' , 'content' : 'not a turtle.' },
303- {
304- 'role' : 'user' ,
305- 'content' : (
306- 'Question: What is Priya doing right now?\n Answer: '
307- + 'Priya is currently '
308- ),
309- },
310- {'role' : 'assistant' , 'content' : 'sleeping.' },
311- {'role' : 'user' , 'content' : augmented_prompt },
312- {'role' : 'assistant' , 'content' : response },
313- ]
314- result = self ._client .chat .completions .create (
286+ full_prompt = augmented_prompt + response
287+ result = self ._client .completions .create (
315288 model = self ._model_name ,
316- messages = messages ,
289+ prompt = full_prompt ,
317290 max_tokens = 1 ,
318291 seed = None ,
319- logprobs = 1 ,
292+ logprobs = True ,
320293 stream = False ,
321294 echo = True ,
322295 )
@@ -341,10 +314,16 @@ def _sample_choice(
341314 )
342315 continue
343316 else :
344- logprobs = result .prompt [0 ].logprobs
345- response_idx = _find_response_start_index (logprobs .tokens )
346- response_log_probs = logprobs .token_logprobs [response_idx :]
317+ # Remove the extra token generated at the end of the prompt.
318+ tokens = result .choices [0 ].logprobs .tokens [:- 1 ]
319+
320+ # Only sum the logprobs for tokens corresponding to the response.
321+ response_start_index = _find_concatenated_subsequence (tokens ,
322+ response )
323+ response_log_probs = (
324+ result .choices [0 ].logprobs .token_logprobs [response_start_index :])
347325 score = sum (response_log_probs )
326+
348327 return score
349328
350329 raise language_model .InvalidResponseError (
@@ -579,7 +558,7 @@ def __init__(
579558
580559 self ._model = None
581560 if model_name .startswith ('google/' ):
582- self ._model = Default (
561+ self ._model = DefaultCompletion (
583562 model_name = model_name ,
584563 api_key = api_key ,
585564 measurements = measurements ,
0 commit comments