diff options
| author | vin <git@vineetk.net> | 2025-07-19 01:51:36 -0400 |
|---|---|---|
| committer | vin <git@vineetk.net> | 2025-07-19 01:51:36 -0400 |
| commit | e4781586464f38f7b3ef1a663b2a50cca6cd2b56 (patch) | |
| tree | 0c0470037abba6b36b42d4028b81b0c4d925549b | |
| parent | bb8c6a7ed9b5b5c450c61408f432980be8e6b120 (diff) | |
respect ratelimit and change output extension to .gpt
| -rw-r--r-- | main.py | 78 |
1 files changed, 38 insertions, 40 deletions
| @@ -1,10 +1,16 @@ | |||
| 1 | import os | 1 | import os |
| 2 | import re | 2 | import re |
| 3 | import sys | 3 | import sys |
| 4 | from openai import OpenAI | 4 | import backoff |
| 5 | import openai | ||
| 5 | from datetime import datetime, timedelta | 6 | from datetime import datetime, timedelta |
| 6 | from tqdm import tqdm | 7 | from tqdm import tqdm |
| 7 | 8 | ||
| 9 | client = openai.OpenAI( | ||
| 10 | #base_url="http://localhost:8080/v1", | ||
| 11 | base_url="https://api.openai.com/v1", | ||
| 12 | ) | ||
| 13 | |||
| 8 | SYSTEM_PROMPT_TEMPLATE = """ | 14 | SYSTEM_PROMPT_TEMPLATE = """ |
| 9 | You are an expert podcast content analyzer. Your task is to identify and extract pre-recorded dynamic advertising segments from podcast transcripts. These ads typically have a distinct tone shift, often using more direct, persuasive language, and frequently include calls to action, product mentions, or specific brand names. | 15 | You are an expert podcast content analyzer. Your task is to identify and extract pre-recorded dynamic advertising segments from podcast transcripts. These ads typically have a distinct tone shift, often using more direct, persuasive language, and frequently include calls to action, product mentions, or specific brand names. |
| 10 | 16 | ||
| @@ -202,28 +208,29 @@ def chunk_transcript( | |||
| 202 | 208 | ||
| 203 | return chunks | 209 | return chunks |
| 204 | 210 | ||
| 205 | def call_openai_api(client: OpenAI, chunk_text: str, system_prompt: str) -> str: | 211 | @backoff.on_exception(backoff.expo, openai.RateLimitError) |
| 212 | def completions_with_backoff(**kwargs): | ||
| 213 | return client.chat.completions.create(**kwargs) | ||
| 214 | |||
| 215 | def call_openai_api(chunk_text: str, system_prompt: str) -> str: | ||
| 206 | """ | 216 | """ |
| 207 | Makes an API call to OpenAI with the given system prompt and transcript chunk. | 217 | Makes an API call to OpenAI with the given system prompt and transcript chunk. |
| 208 | """ | 218 | """ |
| 209 | try: | 219 | response = completions_with_backoff( |
| 210 | response = client.chat.completions.create( | 220 | #model="Gemma-3-4B_32K", |
| 211 | #model="Gemma-3-4B_32K", | 221 | #model="google/gemini-2.0-flash-exp:free", |
| 212 | #model="google/gemini-2.0-flash-exp:free", | 222 | model="gpt-4.1", |
| 213 | model="gpt-4.1", | 223 | messages=[ |
| 214 | messages=[ | 224 | {"role": "system", "content": system_prompt}, |
| 215 | {"role": "system", "content": system_prompt}, | 225 | {"role": "user", "content": f"Input Transcript:\n{chunk_text}"} |
| 216 | {"role": "user", "content": f"Input Transcript:\n{chunk_text}"} | 226 | ], |
| 217 | ], | 227 | temperature=0.0, |
| 218 | temperature=0.0, | 228 | max_tokens=1024, # realistically it'd be under like 512 |
| 219 | ) | 229 | ) |
| 220 | #print(response) | 230 | #print(response) |
| 221 | return response.choices[0].message.content.strip() | 231 | return response.choices[0].message.content.strip() |
| 222 | except Exception as e: | 232 | |
| 223 | print(f"Error calling OpenAI API: {e}") | 233 | def process_file(input_file: str, output_file: str): |
| 224 | return "" | ||
| 225 | |||
| 226 | def process_file(input_file: str, output_file: str, client: OpenAI): | ||
| 227 | with open(input_file, "r", encoding="utf-8") as f: | 234 | with open(input_file, "r", encoding="utf-8") as f: |
| 228 | full_transcript_content = f.read() | 235 | full_transcript_content = f.read() |
| 229 | 236 | ||
| @@ -247,7 +254,11 @@ def process_file(input_file: str, output_file: str, client: OpenAI): | |||
| 247 | # Add the "Your Turn" header before the chunk content | 254 | # Add the "Your Turn" header before the chunk content |
| 248 | user_prompt_content = f"**Your Turn - Input Transcript:**\n{chunk_text_for_api}" | 255 | user_prompt_content = f"**Your Turn - Input Transcript:**\n{chunk_text_for_api}" |
| 249 | 256 | ||
| 250 | ad_timestamps_str = call_openai_api(client, user_prompt_content, SYSTEM_PROMPT_TEMPLATE) | 257 | try: |
| 258 | ad_timestamps_str = call_openai_api(user_prompt_content, SYSTEM_PROMPT_TEMPLATE) | ||
| 259 | except Exception as e: | ||
| 260 | print(f"Error calling OpenAI API: {e}") | ||
| 261 | continue | ||
| 251 | 262 | ||
| 252 | if ad_timestamps_str: | 263 | if ad_timestamps_str: |
| 253 | # Split by newlines in case the model returns multiple segments | 264 | # Split by newlines in case the model returns multiple segments |
| @@ -258,29 +269,16 @@ def process_file(input_file: str, output_file: str, client: OpenAI): | |||
| 258 | f.write("\n".join(all_ad_timestamps)) | 269 | f.write("\n".join(all_ad_timestamps)) |
| 259 | 270 | ||
| 260 | def main(): | 271 | def main(): |
| 261 | # --- Configuration --- | ||
| 262 | api_key = os.getenv("OPENAI_KEY") | ||
| 263 | if not api_key: | ||
| 264 | print("OPENAI_KEY empty") | ||
| 265 | sys.exit(1) | ||
| 266 | |||
| 267 | client = OpenAI( | ||
| 268 | #api_key="none", | ||
| 269 | api_key=api_key, | ||
| 270 | #base_url="http://localhost:8080/v1", | ||
| 271 | base_url="https://api.openai.com/v1", | ||
| 272 | ) | ||
| 273 | |||
| 274 | paths = sys.argv[1:] | 272 | paths = sys.argv[1:] |
| 275 | for i, p in enumerate(paths): | 273 | for p in paths: |
| 276 | out = "".join(p.split(".")[:-1]) + "_gpt.txt" | 274 | out = "".join(p.split(".")[:-1]) + ".gpt" |
| 277 | if os.path.isfile(out) | 275 | if os.path.isfile(out): |
| 278 | paths.remove(i) | 276 | paths.remove(p) |
| 279 | print(paths) | 277 | print(paths) |
| 280 | 278 | ||
| 281 | for p in tqdm(paths): | 279 | for p in tqdm(paths): |
| 282 | out = "".join(p.split(".")[:-1]) + "_gpt.txt" | 280 | out = "".join(p.split(".")[:-1]) + ".gpt" |
| 283 | process_file(p, out, client) | 281 | process_file(p, out) |
| 284 | 282 | ||
| 285 | if __name__ == "__main__": | 283 | if __name__ == "__main__": |
| 286 | main() | 284 | main() |
