import os
assert os.getenv("OPENAI_API_KEY"), \
"Please set the OPEAI_API_KEY environment variable with your OpenAI API key."
01 OpenAI + Timestamp
“Yerevan basement, dates back 200 years. There are canvases in the basement now. It’s an art place.” լուսանկարի հղումը, Հեղինակ՝ Ashkhen Gevorgyan
📌 Նկարագիր
OpenAI
-ը ChatGPT-ն ստեղծող կամպանյան ա։ էսօր սովորելու ենք թե ինչ բան ա API-ը ու ոնց կարանք request-ներ անենք (էս թեմային մի քիչ առնչվել ենք deepl-ով թարմանություններ անելիս): Նաև սովորում ենք environment variable-ների գաղափարը (տերմինալի հրամանակ աշխատացնելով ենք անում դասի ժամանակ, ավելի լավ ա dotenv-ով անել, տես վիդեոն)։
OpenAI
-ով նայում ենք թե ոնց ա կարելի տեքստեր/նկարներ/աուդիո գեներացնել ու ոնց ա կարելի ֆիքսել թե ինչ կառուցվածքով պատասխանի մեզ api-ը (մի քիչ էլ առնչվում ենք pydantic
-ի հետ, որը հետո ենք անցնելու)։
Որպես կիրառություն սարքում ենք ծրագիր որը youtube-ի վիդեո ստանալով քաշում ա իրա տռանսրիպտը (արել էինք նախորդ դասին) ու գենեռացնում ա timestamp-եր (կարևոր թեմաները որ վարկյաններին են սկսվում)
📺 Տեսանյութեր
🏡 Տնային
Կրեատիվությունն ա միակ լիմիտը։ Մի աշխարհ բան ա կարելի անել 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
"OPENAI_API_KEY"] = "sk-..." os.environ[
MAKE SURE TO ALWAYS KEEP YOUR API KEY SECRET! (REMOVE IT FROM YOUR CODE BEFORE SHARING IT)
OpenAI API
Regular Text Completion
import os
from openai import OpenAI
= OpenAI(
client # This is the default and can be omitted
=os.getenv("OPENAI_API_KEY"),
api_key )
= client.responses.create(
response ="gpt-4o",
model="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.",
instructionsinput="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.",
)
0].content[0].text response.output[
'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
0].content[0].text response.output[
'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
= OpenAI()
client
= client.responses.create(
response ="gpt-4.1-mini",
modelinput="Generate a Ghibli style image of cheese",
=[{"type": "image_generation"}],
tools
)
# Save the image to a file
= [
image_data
output.resultfor output in response.output
if output.type == "image_generation_call"
]
if image_data:
= image_data[0]
image_base64 with open("cheese.png", "wb") as f:
f.write(base64.b64decode(image_base64))
0].b64_json result.data[
0] result.data[
from openai import OpenAI
import base64
= OpenAI()
client
= """
prompt Generate a Jibiri style image of cheese.
"""
= client.images.generate(
result ="dall-e-2",
model=prompt
prompt
)
= result.data[0].b64_json
image_base64
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
= requests.get(result.data[0].url)
response # Save the image to a file
with open("cheese.png", "wb") as f:
f.write(response.content)
Audio
import base64
from openai import OpenAI
= OpenAI()
client
= client.chat.completions.create(
completion ="gpt-4o-audio-preview",
model=["text", "audio"],
modalities={"voice": "alloy", "format": "wav"},
audio=[
messages
{"role": "user",
"content": "Is a golden retriever a good family dog?"
}
]
)
# print(completion.choices[0])
= base64.b64decode(completion.choices[0].message.audio.data)
wav_bytes with open("dog.wav", "wb") as f:
f.write(wav_bytes)
Structured out
-
summary -
main_idea
- [timestamp, text]
Transcription
{"summary": ...
"main_idea": ...,
}
"summary"] [
from pydantic import BaseModel
from openai import OpenAI
= OpenAI()
client
class CalendarEvent(BaseModel):
str
name: str
date: list[str]
participants:
= [
messages_lst "role": "system", "content": "Extract the event information."},
{"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
{
]
= client.chat.completions.parse(
completion ="gpt-4o-2024-08-06",
model=messages_lst,
messages=CalendarEvent,
response_format
)
= completion.choices[0].message.parsed event
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'}]
= client.chat.completions.parse(
completion ="gpt-4o-2024-08-06",
model=messages_lst,
messages
)
= completion.choices[0].message.parsed event
0] completion.choices[
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:
str
video_id: str
title: str]
keywords: List[str
publish_date: int
length_seconds:
@staticmethod
def get_days_since_publish(publish_date) -> int:
if isinstance(publish_date, datetime):
= publish_date.strftime("%Y-%m-%d")
publish_date = datetime.strptime(publish_date, "%Y-%m-%d")
publish_date = datetime.now()
current_date 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(
=self.video.video_id,
video_id=self.video.title,
title=self.video.keywords,
keywords=self.video.publish_date,
publish_date=self.video.length
length_seconds
)
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()}")
= self.video.captions.get(language)
captions 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:
= self.video.captions.get(language)
captions if not captions:
raise ValueError(f"No captions available for language: {language}")
=title, output_path=output_path)
captions.download(title
= YouTubeVideo("https://youtu.be/nU3fzO94lBw")
vid = vid.get_metadata() metadata
= vid.get_transcript(language="a.hy", _format="srt") transcript
Fetching transcript for language: a.hy
Available languages: KeysView({'a.hy': <Caption lang="Armenian (auto-generated)" code="a.hy">})
= client.responses.create(
response ="gpt-4o",
model="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.",
instructionsinput=transcript,
)0].content[0].text response.output[
'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 - **Եզրափակիչ խոսքեր**: Հրավիրում ենք դիտելու Գիլբերտի հյուրանոցի խնդիրը:
Հիշեցում բոլոր կետերում ավելի մանրամասն քննարկումը տեսնել մեկնաբանություններում:
- environment variable setup Streamlit
🎲 19 (01)
- ▶️Alex Yemenidjian (WCIT speech)
- 🎲Random link
- 🇦🇲🎶C-rouge (Արի’, իմ սոխակ)
- 🌐🎶Pink Floyd (Dark side of the moon)
- 🤌Կարգին
Նշում։ Floyd-ենք ոչ թե երգեր են գրել, այլ ալբոմներ, նենց որ անարդար չի ամբողջ ալբոմը դնելը :-)