01 OpenAI + Timestamp

image.png “Yerevan basement, dates back 200 years. There are canvases in the basement now. It’s an art place.” լուսանկարի հղումը, Հեղինակ՝ Ashkhen Gevorgyan

Open In Colab (ToDo)

📌 Նկարագիր

📚 Ամբողջական նյութը

OpenAI-ը ChatGPT-ն ստեղծող կամպանյան ա։ էսօր սովորելու ենք թե ինչ բան ա API-ը ու ոնց կարանք request-ներ անենք (էս թեմային մի քիչ առնչվել ենք deepl-ով թարմանություններ անելիս): Նաև սովորում ենք environment variable-ների գաղափարը (տերմինալի հրամանակ աշխատացնելով ենք անում դասի ժամանակ, ավելի լավ ա dotenv-ով անել, տես վիդեոն

OpenAI-ով նայում ենք թե ոնց ա կարելի տեքստեր/նկարներ/աուդիո գեներացնել ու ոնց ա կարելի ֆիքսել թե ինչ կառուցվածքով պատասխանի մեզ api-ը (մի քիչ էլ առնչվում ենք pydantic-ի հետ, որը հետո ենք անցնելու)։

Որպես կիրառություն սարքում ենք ծրագիր որը youtube-ի վիդեո ստանալով քաշում ա իրա տռանսրիպտը (արել էինք նախորդ դասին) ու գենեռացնում ա timestamp-եր (կարևոր թեմաները որ վարկյաններին են սկսվում)

📺 Տեսանյութեր

  1. Տեսություն
  2. Python-Dotenv վիդեո

🏡 Տնային

Կրեատիվությունն ա միակ լիմիտը։ Մի աշխարհ բան ա կարելի անել OpenAI-ով (հայերենի համար ավելի լավ ա Claude-ով անել բայց), կարաք գլխից նաև Streamlit app սարքեք։

📚 Նյութը

OpenAI

First of all pip install openai

Creating API Key

  • https://platform.openai.com/settings/organization/api-keys
  • https://platform.openai.com/docs/overview
SET OPENAI_API_KEY=sk-...
or
SETX OPENAI_API_KEY "sk-..." # saves it permanently

Linux/Mac:

export OPENAI_API_KEY="sk-..."

With Python:

import os
os.environ["OPENAI_API_KEY"] = "sk-..."

MAKE SURE TO ALWAYS KEEP YOUR API KEY SECRET! (REMOVE IT FROM YOUR CODE BEFORE SHARING IT)

import os

assert os.getenv("OPENAI_API_KEY"), \
    "Please set the OPEAI_API_KEY environment variable with your OpenAI API key."

OpenAI API

image.png

image.png

Regular Text Completion

import os
from openai import OpenAI

client = OpenAI(
    # This is the default and can be omitted
    api_key=os.getenv("OPENAI_API_KEY"),
)
response = client.responses.create(
    model="gpt-4o",
    instructions="You are a professional youtube chapter and timestamp generator. I will provide you with a transcript of a video, and you will generate timestamps for the key points discussed in the video. The timestamps should be in the format 'HH:MM:SS' and should be accompanied by a brief description of the content at that timestamp.",
    input="In this video, we will explore the fascinating world of quantum computing. We will start by discussing the basic principles of quantum mechanics and how they differ from classical physics. Then, we will delve into the concept of qubits and how they are used in quantum computers. We will also cover the challenges faced in building practical quantum computers and the potential applications of this technology in various fields such as cryptography, drug discovery, and artificial intelligence. Finally, we will look at some of the leading companies and research institutions working on quantum computing and their latest advancements.",
)

response.output[0].content[0].text
'00:00:00 - Introduction to Quantum Computing  \nOverview of the video and the topics to be covered.\n\n00:00:30 - Basics of Quantum Mechanics  \nExploration of quantum mechanics principles and their differences from classical physics.\n\n00:02:15 - Understanding Qubits  \nExplanation of qubits and their role in quantum computers.\n\n00:04:00 - Building Practical Quantum Computers  \nDiscussion on the challenges in constructing practical quantum computing systems.\n\n00:05:45 - Quantum Computing Applications  \nPotential uses in cryptography, drug discovery, and artificial intelligence.\n\n00:08:30 - Leading Companies and Research  \nInsight into companies and institutions at the forefront of quantum computing advancements.'
type(response)
openai.types.responses.response.Response
response.output[0].content[0].text
'To check if a Python object is an instance of a specific class, you can use the `isinstance()` function. Here\'s the syntax:\n\n```python\nisinstance(object, classinfo)\n```\n\n- `object` is the instance you want to check.\n- `classinfo` is the class (or a tuple of classes) you want to check against.\n\nHere’s an example:\n\n```python\nclass MyClass:\n    pass\n\nobj = MyClass()\n\n# Check if obj is an instance of MyClass\nif isinstance(obj, MyClass):\n    print("obj is an instance of MyClass")\nelse:\n    print("obj is not an instance of MyClass")\n```\n\nYou can also check against a tuple of classes:\n\n```python\nclass AnotherClass:\n    pass\n\n# Check if obj is an instance of MyClass or AnotherClass\nif isinstance(obj, (MyClass, AnotherClass)):\n    print("obj is an instance of MyClass or AnotherClass")\n```\n\nThis function returns `True` if the `object` is an instance of the specified class or any subclass thereof.'

Image

from openai import OpenAI
import base64

client = OpenAI() 

response = client.responses.create(
    model="gpt-4.1-mini",
    input="Generate a Ghibli style image of cheese",
    tools=[{"type": "image_generation"}],
)

# Save the image to a file
image_data = [
    output.result
    for output in response.output
    if output.type == "image_generation_call"
]
    
if image_data:
    image_base64 = image_data[0]
    with open("cheese.png", "wb") as f:
        f.write(base64.b64decode(image_base64))
result.data[0].b64_json
result.data[0]
from openai import OpenAI
import base64
client = OpenAI()

prompt = """
Generate a Jibiri style image of cheese.
"""

result = client.images.generate(
    model="dall-e-2",
    prompt=prompt
)

image_base64 = result.data[0].b64_json

if image_base64 is None:
    print(result.data[0].url)
# image_bytes = base64.b64decode(image_base64)

# # Save the image to a file
# with open("cheese.png", "wb") as f:
#     f.write(image_bytes)
https://oaidalleapiprodscus.blob.core.windows.net/private/org-ttpmtIE2I4svAF3GF4fDbAI6/user-ikPOmBgtK5dBqbZAFApYEkzD/img-6fshySmSXaSaAEYgCuNjDZv6.png?st=2025-06-28T07%3A21%3A26Z&se=2025-06-28T09%3A21%3A26Z&sp=r&sv=2024-08-04&sr=b&rscd=inline&rsct=image/png&skoid=475fd488-6c59-44a5-9aa9-31c4db451bea&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2025-06-27T14%3A51%3A18Z&ske=2025-06-28T14%3A51%3A18Z&sks=b&skv=2024-08-04&sig=QdN1QAQjfmBFQLAtzo2iJP3KODGLSzyc58akUStCXXw%3D
# get image from url
import requests
response = requests.get(result.data[0].url)
# Save the image to a file
with open("cheese.png", "wb") as f:
    f.write(response.content)

Audio

import base64
from openai import OpenAI

client = OpenAI()

completion = client.chat.completions.create(
    model="gpt-4o-audio-preview",
    modalities=["text", "audio"],
    audio={"voice": "alloy", "format": "wav"},
    messages=[
        {
            "role": "user",
            "content": "Is a golden retriever a good family dog?"
        }
    ]
)


# print(completion.choices[0])

wav_bytes = base64.b64decode(completion.choices[0].message.audio.data)
with open("dog.wav", "wb") as f:
    f.write(wav_bytes)

Structured out

summary - 
main_idea - 

Transcription - [timestamp, text]

{
    "summary": ...
    "main_idea": ...,
}

["summary"]
from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class CalendarEvent(BaseModel):
    name: str
    date: str
    participants: list[str]

messages_lst = [
        {"role": "system", "content": "Extract the event information."},
        {"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
    ]


completion = client.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=messages_lst,
    response_format=CalendarEvent,
)

event = completion.choices[0].message.parsed

History

messages_lst.append(
    {
        "role": "assistant",
        "content": f"Event Name: {event.name}, Date: {event.date}, Participants: {', '.join(event.participants)}"
    }
)

messages_lst.append(
    {
        "role": "user",
        "content": f"Output the date in ISO format"
    }
)
messages_lst
[{'role': 'system', 'content': 'Extract the event information.'},
 {'role': 'user',
  'content': 'Alice and Bob are going to a science fair on Friday.'},
 {'role': 'assistant',
  'content': 'Event Name: Science Fair, Date: 2023-11-03, Participants: Alice, Bob'},
 {'role': 'assistant',
  'content': 'Event Name: Science Fair, Date: 2023-11-03, Participants: Alice, Bob'},
 {'role': 'user', 'content': 'Output the date in ISO format'}]
completion = client.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=messages_lst,
)

event = completion.choices[0].message.parsed
completion.choices[0]
ParsedChoice[NoneType](finish_reason='stop', index=0, logprobs=None, message=ParsedChatCompletionMessage[NoneType](content='Event Name: Science Fair, Date: 2023-11-03 (ISO format), Participants: Alice, Bob', refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=None, parsed=None))

🛠️ Գործնական

Timestamp generator

from typing import List
from pytubefix import YouTube
from datetime import datetime
from dataclasses import dataclass
@dataclass()
class VideoInfo:
    video_id: str
    title: str
    keywords: List[str]
    publish_date: str  
    length_seconds: int
    
    @staticmethod
    def get_days_since_publish(publish_date) -> int:
        if isinstance(publish_date, datetime):
            publish_date = publish_date.strftime("%Y-%m-%d")
        publish_date = datetime.strptime(publish_date, "%Y-%m-%d")
        current_date = datetime.now()
        return (current_date - publish_date).days
        
        
    def __post_init__(self):
        if not isinstance(self.video_id, str):
            raise ValueError("video_id must be a string")
        if not isinstance(self.length_seconds, int):
            raise ValueError("length_seconds must be an integer")
        
        self.days_since_publish = self.get_days_since_publish(self.publish_date)
class YouTubeVideo:
    def __init__(self, url: str):
        self.video = YouTube(url)

    def get_metadata(self) -> VideoInfo:
        return VideoInfo(
            video_id=self.video.video_id,
            title=self.video.title, 
            keywords=self.video.keywords,
            publish_date=self.video.publish_date,
            length_seconds=self.video.length
        )
    
    def get_transcript(self, language: str = "de", _format = "txt") -> str:
        print(f"Fetching transcript for language: {language}")
        print(f"Available languages: {self.video.captions.keys()}")
        captions = self.video.captions.get(language)
        if not captions:
            raise ValueError(f"No captions available for language: {language}")
        if _format == "txt":
            self.text = captions.generate_txt_captions()
        elif _format == "srt":
            self.text = captions.generate_srt_captions()
        else:
            raise ValueError(f"Unsupported format: {_format}. Supported formats are 'txt' and 'srt'.")
        
        return self.text
    
    def download_transcript(self, language: str = "de", title: str = "transcript", output_path: str = "transcript.txt") -> None:
        captions = self.video.captions.get(language)
        if not captions:
            raise ValueError(f"No captions available for language: {language}")
        captions.download(title=title, output_path=output_path)
        
vid = YouTubeVideo("https://youtu.be/nU3fzO94lBw")
metadata = vid.get_metadata()
transcript = vid.get_transcript(language="a.hy", _format="srt")
Fetching transcript for language: a.hy
Available languages: KeysView({'a.hy': <Caption lang="Armenian (auto-generated)" code="a.hy">})
response = client.responses.create(
    model="gpt-4o",
    instructions="You are a professional youtube chapter and timestamp generator. I will provide you with a transcript of a video, and you will generate timestamps for the key points discussed in the video. The timestamps should be in the format 'HH:MM:SS' and should be accompanied by a brief description of the content at that timestamp. The descriptions should be in the same language as the transcript.",
    input=transcript,
)
response.output[0].content[0].text
'00:00:00 - **Ծիրանների հաշվարկ**: Խոսք ծիրանների և խնձորների քանակի վրա:  \n00:00:12 - **Խնձորների հաշվարկ**: Ուսումնասիրում ենք խնձորների թիվը:  \n00:00:26 - **Համեմատություն**: Քննարկում ենք խնձորների և ծիրանների քանակի համեմատությունը:  \n00:00:56 - **Մաթեմատիկական պատկերացում**: Ներդրվում է բնական թվերի բազմության գաղափարը:  \n00:01:18 - **0-ից 1 միջակայքը**: Քննարկվում է 0-ից 1 թվերի միջակայքի գաղափարը:  \n00:01:40 - **Համեմատական վերլուծություն**: Ուսումնասիրում ենք երկու հավաքածուների հզորությունները:  \n00:02:43 - **Հավասարության գաղափար**: Հնարավորությունը n-ի և 0-1 միջակայքի հավասարության:  \n00:04:00 - **Հահաքանակների օրինակ**: Նորից հայտարարերը, բայց այս անգամ ռուսերեն:  \n00:05:40 - **Անվերջության քննարկում**: Ինչպես համեմատել երկու անվերջությունների:  \n00:07:16 - **Անհամապատասխանություն**: Բացատրում, որ տարերի թվի հաշվարկն անհնար է 0-1 միջակայքի համար:  \n00:11:04 - **Անվերջություն ավելի շատ է**: Հասկանում ենք, որ 0-1 միջակայքը պարունակում է ավելի շատ թվեր քան բնական թվերը:  \n00:12:15 - **Եզրափակիչ խոսքեր**: Հրավիրում ենք դիտելու Գիլբերտի հյուրանոցի խնդիրը:  \n\nՀիշեցում բոլոր կետերում ավելի մանրամասն քննարկումը տեսնել մեկնաբանություններում:'
print(response.output[0].content[0].text)
00:00:00 - **Ծիրանների հաշվարկ**: Խոսք ծիրանների և խնձորների քանակի վրա:  
00:00:12 - **Խնձորների հաշվարկ**: Ուսումնասիրում ենք խնձորների թիվը:  
00:00:26 - **Համեմատություն**: Քննարկում ենք խնձորների և ծիրանների քանակի համեմատությունը:  
00:00:56 - **Մաթեմատիկական պատկերացում**: Ներդրվում է բնական թվերի բազմության գաղափարը:  
00:01:18 - **0-ից 1 միջակայքը**: Քննարկվում է 0-ից 1 թվերի միջակայքի գաղափարը:  
00:01:40 - **Համեմատական վերլուծություն**: Ուսումնասիրում ենք երկու հավաքածուների հզորությունները:  
00:02:43 - **Հավասարության գաղափար**: Հնարավորությունը n-ի և 0-1 միջակայքի հավասարության:  
00:04:00 - **Հահաքանակների օրինակ**: Նորից հայտարարերը, բայց այս անգամ ռուսերեն:  
00:05:40 - **Անվերջության քննարկում**: Ինչպես համեմատել երկու անվերջությունների:  
00:07:16 - **Անհամապատասխանություն**: Բացատրում, որ տարերի թվի հաշվարկն անհնար է 0-1 միջակայքի համար:  
00:11:04 - **Անվերջություն ավելի շատ է**: Հասկանում ենք, որ 0-1 միջակայքը պարունակում է ավելի շատ թվեր քան բնական թվերը:  
00:12:15 - **Եզրափակիչ խոսքեր**: Հրավիրում ենք դիտելու Գիլբերտի հյուրանոցի խնդիրը:  

Հիշեցում բոլոր կետերում ավելի մանրամասն քննարկումը տեսնել մեկնաբանություններում:
Streamlit - environment variable setup

🎲 19 (01)

Նշում։ Floyd-ենք ոչ թե երգեր են գրել, այլ ալբոմներ, նենց որ անարդար չի ամբողջ ալբոմը դնելը :-)

Flag Counter