Skip to content

Commit a6096b3

Browse files
jzleibocopybara-github
authored andcommitted
Fix DefaultCompletion version of together_ai wrapper and remove Gemma2 support since together_ai no longer hosts it. Tested with Gemma3.
PiperOrigin-RevId: 801747048 Change-Id: I5c534ae225078a6fee2af478e21df988dbba1c87
1 parent 0b72d64 commit a6096b3

2 files changed

Lines changed: 47 additions & 68 deletions

File tree

concordia/language_model/together_ai.py

Lines changed: 45 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@
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-
3228
OpenAI open weights family:
3329
- openai/gpt-oss-120b
3430
- openai/gpt-oss-20b
@@ -38,6 +34,7 @@
3834
import concurrent.futures
3935
import os
4036
import random
37+
import re
4138
import time
4239

4340
from absl import logging
@@ -62,39 +59,40 @@
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

10098
def _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?\nAnswer: Jake is ',
301-
},
302-
{'role': 'assistant', 'content': 'not a turtle.'},
303-
{
304-
'role': 'user',
305-
'content': (
306-
'Question: What is Priya doing right now?\nAnswer: '
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,

examples/actor_development.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@
158158
"source": [
159159
"test = model.sample_choice(\n",
160160
" prompt=('For Richard Rorty, is moral progress like getting '\n",
161-
" 'a progressively clearer picture of something true and deep?'),\n",
162-
" responses=('yes', 'no'))\n",
161+
" 'a progressively clearer picture of something true and deep?\\n'),\n",
162+
" responses=('Yes', 'No'))\n",
163163
"print(test)"
164164
],
165165
"outputs": [],

0 commit comments

Comments
 (0)