Wikipedie:GPT generátor alternativních textů k obrázkům

Pro Nejlepší a někdy i Dobrý článek mohou recenzenti požadovat, aby obrázky měly alternativní text pro nevidomé, tzv. alt (Nápověda:Alternativní text). Následující program v Pythonu 3 je založený na umělé inteligenci. Projde zadaný článek české Wikipedie (jeho jméno zapište přímo do programu, jde o "holý" program bez uživatelského rozhraní) a ke každému obrázku vypíše požadovaný počet návrhů, jak by alt mohl vypadat. Protože přes API provolává model řady GPT, je potřeba mít na stránkách firmy OpenAI zakoupeno právo model takto používat (https://openai.com/api/). Cena: v květnu 2024, kdy program vznikl, vyšla stovka návrhů altů řádově na jeden dolar.


""" Generátor návrhů na alternativní popisky (alt) k obrázkům na zadané stránce české Wikipedie
Použití:
- níže zadejte
--  název článku na české Wikipedii, který chcete vylepšit   /page_title/ 
--  počet návrhů k jednomu obrázku, ze kterých budete vybírat nejzdařilejší   /suggestions/
--  svůj api_key pro OpenAI APIs   /my_api_key/ - lze zakoupit na webu firmy OpenAI
- spusťte program v Pythonu 3 (je potřeba mít nainstalovaný balíček openai)
- na Wikipedii otevřete článek klasickém editoru
- z výpisu vyberte pro každý obrázek nejzdařilejší návrh
- do odkazu na obrázek vložte "|alt=popis", a to na konec, před uzavírací dvojité hranaté závorky
--  např. [[Soubor:a.png|náhled|Písmeno A|alt=Černé tiskací A na bílém pozadí.]]
- případně ještě zeditujte, pokud návrh popisu má chyby (pozor, program občas něco nepozná nebo halucinuje)
- stránku na Wikipedii uložte
Neumí vektorovou grafiku. Vynechává galerie, obrázky vyvolané šablonami, obrázky bez popisků;
pro tyto obrázky je možné samostatně zavolat funkci altpopis(pic) níže s jménem obrázku jako argumentem.
Autor programu: Jan Spousta
"""
import requests
import re
import time
from openai import OpenAI

# Vstupy: následující dva řádky změň podle své potřeby
page_title = "Fafertin"  # jméno článku v uvozovkách
suggestions = 2  # počet návrhů popisky ke každému obrázku (čím víc, tím déle to trvá a víc peněz stojí)

client = OpenAI(api_key=my_api_key)   # za my_api_key dosadit klíč od firmy OpenAI - lze ho zakoupit na jejich webu


# Vlastní program
def get_image_names(page_title):
    """
    Funkce vytvoří seznam obrázků použitých ve wikitextu stránky v argumentu
    """
    # Define the API endpoint for Czech Wikipedia
    api_url = "https://cs.wikipedia.org/w/api.php"

    # Set parameters for the API request to get wikicode
    params = {
        'action': 'query',
        'format': 'json',
        'titles': page_title,
        'prop': 'revisions',
        'rvprop': 'content',
        'rvslots': '*'
    }

    try:
        # Make the API request
        response = requests.get(api_url, params=params)
        data = response.json()

        # Navigate through the JSON response to find the page's wikicode
        pages = data['query']['pages']
        page_id = next(iter(pages))
        wikicode = pages[page_id]['revisions'][0]['slots']['main']['*']

        # Use regular expression to find all instances of image links
        image_names = re.findall(r'\[\[(?:File|Image|Soubor):(.+?)\|', wikicode)

        return image_names

    except Exception:
        print("Page not found or other error in API response.")
        return []


def altpopis(pic):
    """
    Funkce k zadanému obrázku na Commons navrhne popis v češtině pomocí modelu gpt-4-turbo; cenově vychází
    v řádu 1 USD za 100 popisků. Vstupem je řetězec obsahující obrázek na Commons, např. "Brie noir.jpg".
    Neumí vektorovou grafiku.
    """

    prompt = """
       Krátce popiš obrázek. Soustřeď se na hlavní vyobrazený předmět.
       Začni druhem obrázku, např. Rytina muže... nebo Černobílá fotografie skupiny lidí...
       Nevypisuj své další znalosti o předmětu, který je zobrazen.
       """
    commons_path = "https://commons.wikimedia.org/wiki/Special:FilePath/"
    msg = [{
        "role": "user",
        "content": [
            {"type": "text",      "text": prompt},
            {"type": "image_url", "image_url": {"url": commons_path + pic,}, },
        ],
    }]

    tries, altdesc = 0, "Popis obrázku se nepodařilo získat"
    while tries < 4:
        tries += 1
        try:
            response = client.chat.completions.create(model="gpt-4-turbo", messages=msg, max_tokens=600)
            altdesc = response.choices[0].message.content
            break
        except Exception:
            time.sleep(3)

    print("|alt="+altdesc)
    return altdesc


# Vyhledá si obrázky, postupně k nim vygeneruje návrhy popisek a vypíše je.
obrazky = get_image_names(page_title)
for img in obrazky:
    print(img)
    print("\n")
    for i in range(suggestions):
        altpopis(img)
        print("\n")