Files
903c5e9e93 Fix the number of completions generation by OpenAI API (#260)
* move rejection sampling within its own directory

* move rejection sampling within its own directory

* add api-based models to generating completions

* debug

* debug

* debug

* debug

* debug

* do not apply tokenization with chat template

* change the tokenizer

* change the tokenizer

* fix template

* fix arg issue

* add mode to arg

* add mode to arg

* change the skill

* remove main from api_generate.py

* modify template chat

* modify template chat

* return only text

* return only text

* return only text

* fix dict

* fix dict

* fix dict

* fix dict

* fix dict

* fix dict

* add LM as a scorer

* add LM as a scorer

* add LM as a scorer

* add LM as a scorer

* change the name of the model

* fix rank bug

* process score

* process score

* edit the template

* extract score

* compute scores for reference responses

* compute scores for reference responses

* add tqdm

* add tqdm

* fix score bug

* fix item bug

* fix item bug

* fixed code style

* fixed code style

* .idea added to .gitignore

* .idea dir removed

* remove unused llm_as_judge file

* Update rejection_sampling.md

* fix the path to rejection sampling files

* update readme

* remove unused args

* use args

* remove args

* fix chatgpt completion

* fix chatgpt completion

* fix chatgpt completion

* fix bug

* fix format conversation

* fix minor bug

* fix minor bug

* fix minor bug

* fix minor bug

* fix parsing response

* test judgment

* update format

* update format

* debug

* debug

* debug

* fix

* format fixed

* format fixed

* fix bug

* fix bug

* fix bug

* fix bug

* add comment

* update n

* duplicate

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* generate n completions per prompt

* debug

* improve response

* improve response

* completions n

* completions n

* completions n

* remove debug

* fix outputs structure

* fix outputs structure

* fix outputs structure

* fix outputs structure

* fix outputs structure

* push a new branch

* black

* use consistent naming

* add debugging output

* push changes

* push changes

* update docs

* filter out prompts which are beyond the model's max token length

* quick change

* quick fix on bash script

* quick fix

---------

Co-authored-by: Costa Huang <[email protected]>
2024-08-15 20:40:10 -04:00

96 lines
3.7 KiB
Python

# main.py
import asyncio
import re
from dataclasses import dataclass
from typing import List, Optional
import numpy as np
from openai import AsyncOpenAI
from tqdm.asyncio import tqdm
from open_instruct.rejection_sampling.prompt_templates import (
get_generation_template,
get_judgment_template,
)
@dataclass
class LLMGenerationConfig:
num_completions: int = 64
model: str = "gpt-3.5-turbo-0125"
max_parallel_requests: Optional[int] = None
def __post_init__(self):
if "gpt-3.5" in self.model:
self.max_parallel_requests = 11
elif "gpt-4" in self.model:
self.max_parallel_requests = 13
@dataclass
class Args:
output_path: Optional[str] = None
num_trials: int = 1
class LLMProcessor:
def __init__(self, config: LLMGenerationConfig):
self.config = config
self.async_client = AsyncOpenAI()
async def process_text(self, data: dict, i: int, limiter: asyncio.Semaphore, args: Args, gen_args: Args):
if args.mode == "generation":
template = get_generation_template(args.skill)
text = template.format(prompt=data)
elif args.mode == "judgement": # judgment mode
template = get_judgment_template(args.skill)
text = template.format(prompt=data["prompt"], response=data["response"])
else:
raise ValueError(f"Invalid mode: {args.mode}")
async with limiter:
while True:
try:
response = await self.async_client.chat.completions.create(
model=self.config.model,
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": text},
],
n=gen_args.num_completions, # Request multiple completions
temperature=gen_args.temperature, # Sampling temperature
max_tokens=gen_args.response_length, # Maximum tokens in the response
top_p=gen_args.top_p, # Top-P (nucleus) sampling
stop=None, # Add stopping criteria if needed
)
# Collect all completions if `n > 1`
completions = [choice.message.content for choice in response.choices]
if args.mode == "generation":
response = completions
elif args.mode == "judgement":
# If in judgment mode, process the completions (for example, extracting scores)
scores = []
for completion in completions:
match = re.search(r"Total score:\s*(\d+)", completion)
if match:
score = int(match.group(1))
else:
score = -1
scores.append(score)
response = np.mean(scores)
else:
raise ValueError(f"Invalid mode: {args.mode}")
break
except Exception as e:
print(f"Error in {i}: {e}")
await asyncio.sleep(30)
return response
async def process_batch(self, data_list: List[dict], args: Args, gen_args: Args):
limiter = asyncio.Semaphore(self.config.max_parallel_requests)
tasks = [self.process_text(data, i, limiter, args, gen_args) for i, data in enumerate(data_list)]
# Use tqdm to track progress
return await tqdm.gather(*tasks, total=len(tasks), desc="Processing Batch")