Sdílet prostřednictvím


Vývoj aplikací pro uvažování s využitím modelů DeepSeek ve Foundry Azure AI pomocí OpenAI SDK

Naučte se používat modely odůvodnění, jako je DeepSeek v Azure OpenAI, pomocí sady OpenAI SDK pro Python.

Tento článek ukazuje několik osvědčených postupů pro integraci modelů odůvodnění:

  • Ověřování bez klíčů: Používejte spravované identity nebo přihlašovací údaje pro vývojáře místo klíčů rozhraní API.
  • Asynchronní operace: K lepšímu výkonu používejte asynchronní funkce.
  • Proudové odpovědi: Poskytněte uživatelům okamžitou zpětnou vazbu.
  • Oddělení odůvodnění: Oddělte kroky odůvodnění od konečného výstupu.
  • Správa prostředků: Po použití vyčistěte prostředky.

Stavební blok DeepSeek

Prozkoumejte ukázku stavebního bloku DeepSeek . Ukazuje, jak pomocí klientské knihovny OpenAI volat model DeepSeek-R1 a generovat odpovědi na zprávy uživatelů.

Přehled architektury

Následující diagram znázorňuje jednoduchou architekturu ukázkové aplikace: Diagram znázorňující architekturu z klienta do back-endové aplikace.

Chatovací aplikace běží jako aplikace kontejneru Azure. Aplikace používá spravovanou identitu s ID Microsoft Entra k ověřování pomocí Azure OpenAI místo klíče rozhraní API. Aplikace používá Azure OpenAI k vygenerování odpovědí na zprávy uživatelů.

Aplikace spoléhá na tyto služby a komponenty:

  • Aplikace Python Quart , která používá balíček klientské knihovny OpenAI k vygenerování odpovědí na zprávy uživatelů
  • Základní front-end HTML/JS, který streamuje odpovědi z back-endu pomocí řádků JSON přes readableStream
  • Soubory Bicep pro zřizování prostředků Azure, včetně Azure AI Services, Azure Container Apps, Azure Container Registry, Azure Log Analytics a rolí RBAC.

Náklady

Pokud chcete zachovat nízké náklady, tato ukázka používá u většiny prostředků základní nebo spotřební cenové úrovně. Podle potřeby upravte úroveň a odstraňte prostředky, abyste se vyhnuli poplatkům.

Přečtěte si více informací o nákladech v ukázkovém úložišti.

Požadavky

Vývojový kontejner obsahuje všechny závislosti, které potřebujete pro tento článek. Můžete ho spustit v GitHub Codespaces (v prohlížeči) nebo místně pomocí editoru Visual Studio Code.

Pokud chcete postupovat podle tohoto článku, ujistěte se, že splňujete tyto požadavky:

Otevřené vývojové prostředí

Podle těchto kroků nastavte předem nakonfigurované vývojové prostředí se všemi požadovanými závislostmi.

GitHub Codespaces spouští vývojový kontejner spravovaný GitHubem pomocí editoru Visual Studio Code pro web jako rozhraní. K nejjednoduššímu nastavení použijte GitHub Codespaces, protože obsahuje potřebné nástroje a závislosti předinstalované pro tento článek.

Důležité

Všechny účty GitHubu můžou každý měsíc používat Codespaces až 60 hodin zdarma se dvěma základními instancemi. Podrobnější informace najdete v GitHub Codespaces o měsíčně zahrnutém úložišti a hodinách jádra.

Pomocí následujícího postupu vytvořte nový GitHub Codespace ve main větvi Azure-Samples/deepseek-python úložiště GitHub.

  1. Klikněte pravým tlačítkem myši na následující tlačítko a vyberte Otevřít odkaz v novém okně. Tato akce umožňuje mít vývojové prostředí a otevřenou dokumentaci vedle sebe.

    Otevřít v GitHub Codespaces

  2. Na stránce Create codespace (Vytvořit kódový prostor) zkontrolujte a pak vyberte Create new codespace (Vytvořit nový prostor kódu).

  3. Počkejte, až se codespace spustí. Může to trvat několik minut.

  4. Přihlaste se k Azure pomocí Azure Developer CLI v terminálu v dolní části obrazovky.

    azd auth login
    
  5. Zkopírujte kód z terminálu a vložte ho do prohlížeče. Postupujte podle pokynů k ověření pomocí účtu Azure.

Proveďte zbývající úlohy v tomto vývojovém kontejneru.

Nasazení a spuštění

Ukázkové úložiště obsahuje všechny soubory kódu a konfigurace, které potřebujete k nasazení chatovací aplikace do Azure. Pomocí těchto kroků nasaďte chatovací aplikaci do Azure.

Nasazení chatovací aplikace do Azure

Důležité

Prostředky Azure vytvořené v této části začnou okamžitě generovat náklady. Tyto prostředky můžou i nadále vyžadovat náklady, i když příkaz zastavíte před dokončením.

  1. Spusťte následující příkaz Azure Developer CLI pro zřizování prostředků Azure a nasazení zdrojového kódu:

    azd up
    
  2. Pomocí následující tabulky odpovězte na výzvy:

    Podnět Odpověď
    Název prostředí Udržte to krátké a pište malými písmeny. Přidejte svoje jméno nebo alias. Například: chat-app. Používá se jako součást názvu skupiny prostředků.
    Předplatné Vyberte předplatné, ve kterém chcete prostředky vytvořit.
    Umístění (pro hostování) V seznamu vyberte umístění blízko vás.
    Umístění modelu DeepSeek V seznamu vyberte umístění blízko vás. Pokud je stejné umístění dostupné jako vaše první umístění, vyberte ho.
  3. Počkejte, až se aplikace nasadí. Nasazení obvykle trvá 5 až 10 minut.

Použijte chatovací aplikaci pro kladení otázek velkému jazykovému modelu

  1. Po nasazení se v terminálu zobrazí adresa URL.

  2. Vyberte adresu URL označenou Deploying service web k otevření chatovací aplikace v prohlížeči.

    Snímek obrazovky chatovací aplikace v prohlížeči s dotazem v textovém poli chatu spolu s odpovědí

  3. V prohlížeči položte otázku týkající se nahraného obrázku, například "Kdo maloval Mona Lisa?"

  4. Azure OpenAI poskytuje odpověď prostřednictvím odvozování modelu a výsledek se zobrazí v aplikaci.

Prozkoumání ukázkového kódu

Služba OpenAI i Azure OpenAI používají společnou klientskou knihovnu Pythonu, ale musíte provést několik malých změn kódu pro koncové body Azure OpenAI. Tato ukázka používá model DeepSeek-R1 odůvodnění k vygenerování odpovědí v jednoduché chatovací aplikaci.

Nastavení a ověřování

Soubor src\quartapp\chat.py začíná nastavením a konfigurací ověřování bez klíčů.

Nastavení infrastruktury

Skript používá Quart, asynchronní webový framework, k vytvoření Blueprint, pojmenovaného chat. Tento Blueprint definuje trasy aplikace a spravuje její životní cyklus.

bp = Blueprint("chat", __name__, template_folder="templates", static_folder="static")

Element Blueprint definuje / a /chat/stream trasy a @bp.before_app_serving a @bp.after_app_serving háky životního cyklu.

Inicializace s ověřováním bez klíčů

Následující fragment kódu zpracovává ověřování.

Poznámka:

Hook @bp.before_app_serving inicializuje klienta OpenAI a zpracovává ověřování. Tento přístup je kritický pro bezpečný přístup k modelům hostovaným v Azure DeepSeek-R1.

Strategie ověřování se přizpůsobí prostředí:

  • V produkčním prostředí: Používá přihlašovací údaje spravované identity s ID klienta Azure, aby se zabránilo ukládání citlivých klíčů. Tato metoda je zabezpečená a škálovatelná pro aplikace nativní pro cloud.
  • Vývoj: Používá přihlašovací údaje Azure Developer CLI s ID tenanta Azure ke zjednodušení místního testování pomocí přihlašovací relace Azure CLI vývojáře.
@bp.before_app_serving
async def configure_openai():
    if os.getenv("RUNNING_IN_PRODUCTION"):
        client_id = os.environ["AZURE_CLIENT_ID"]
        bp.azure_credential = ManagedIdentityCredential(client_id=client_id)
    else:
        tenant_id = os.environ["AZURE_TENANT_ID"]
        bp.azure_credential = AzureDeveloperCliCredential(tenant_id=tenant_id)

Tento přístup ověřování bez klíčů poskytuje:

  • Lepší zabezpečení: Žádné klíče rozhraní API uložené v kódu nebo proměnných prostředí.
  • Jednodušší správa: Nemusíte obměňovat klíče ani spravovat tajné kódy.
  • Hladké přechody: Stejný kód funguje jak ve vývoji, tak v produkčním prostředí.

Nastavení zprostředkovatele tokenů

V následujícím fragmentu kódu vytvoří zprostředkovatel tokenu nosný token pro ověřování požadavků na služby Azure OpenAI. Automaticky vygeneruje a aktualizuje tyto tokeny pomocí nakonfigurovaných přihlašovacích údajů.

bp.openai_token_provider = get_bearer_token_provider(
    bp.azure_credential, "https://cognitiveservices.azure.com/.default"
)

Konfigurace klienta Azure OpenAI

Existují dva možné klienty, AzureOpenAI a AsyncAzureOpenAI. Následující fragment kódu používá AsyncAzureOpenAI společně s asynchronní Quart architekturou pro lepší výkon s souběžnými uživateli:

bp.openai_client = AsyncAzureOpenAI(
    azure_endpoint=os.environ["AZURE_INFERENCE_ENDPOINT"],
    azure_ad_token_provider=openai_token_provider,
    api_version="2024-10-21",
  • base_url: Odkazuje na koncový bod pro odvozovací bod DeepSeek hostovaný v Azure.
  • api_key: Používá dynamicky vygenerovaný klíč rozhraní API od zprostředkovatele tokenu.
  • api-version: Určuje verzi rozhraní API podporující modely DeepSeek.

Konfigurace názvu nasazení modelu

Následující fragment kódu nastaví verzi modelu DeepSeek získáním názvu nasazení z konfigurace vašeho prostředí. Přiřadí název bp.model_deployment_name proměnné, aby byl přístupný v celé aplikaci. Tento přístup umožňuje změnit nasazení modelu bez aktualizace kódu.

bp.model_deployment_name = os.getenv("AZURE_DEEPSEEK_DEPLOYMENT")

Poznámka:

V Azure OpenAI nepoužíváte přímo názvy modelů jako gpt-4o nebo deepseek-r1. Místo toho vytváříte nasazení, což jsou pojmenované instance modelů ve vašem prostředku Azure OpenAI. Tento přístup nabízí následující výhody:

  • Abstrakce: Udržuje názvy nasazení mimo kód pomocí proměnných prostředí.
  • Flexibilita: Umožňuje přepínat mezi různými nasazeními DeepSeek beze změny kódu.
  • Konfigurace specifická pro prostředí: Umožňuje používat různá nasazení pro vývoj, testování a produkci.
  • Správa prostředků: Každé nasazení Azure má vlastní kvótu, omezování a monitorování.

Správa životního cyklu

Následující fragment kódu zabraňuje úniku prostředků zavřením asynchronního klienta Azure OpenAI při vypnutí aplikace. Háček @bp.after_app_serving zajišťuje řádné vyčištění prostředků.

@bp.after_app_serving
async def shutdown_openai():
    await bp.openai_client.close()

Streamovací funkce správce chatu

Funkce chat_handler() spravuje interakce uživatelů s modelem DeepSeek-R1 přes trasu chat/stream . Streamuje odpovědi zpět klientovi v reálném čase a zpracovává je. Funkce extrahuje zprávy z datové části JSON.

Implementace streamování

  1. Funkce response_stream začíná přijímáním zpráv z klienta.

    • request_messages: Trasa očekává datovou část JSON obsahující uživatelské zprávy.
    @bp.post("/chat/stream")
    async def chat_handler():
       request_messages = (await request.get_json())["messages"]
    
  2. V dalším kroku funkce streamuje odpovědi z rozhraní OpenAI API. Kombinuje systémové zprávy, jako je "Jste užitečný asistent" se zprávami poskytovanými uživatelem.

    @stream_with_context
    async def response_stream():
        all_messages = [
            {"role": "system", "content": "You are a helpful assistant."},
        ] + request_messages
    
  3. Dále funkce vytvoří žádost o dokončení chatové konverzace pomocí streamování.

    Metoda chat.completions.create odešle zprávy do DeepSeek-R1 modelu. Tento stream=True parametr umožňuje streamování odezvy v reálném čase.

      chat_coroutine = bp.openai_client.chat.completions.create(
          model=bp.openai_model,
          messages=all_messages,
          stream=True,
      )
    
  4. Následující fragment kódu zpracovává odpovědi na streamování z DeepSeek-R1 modelu a zpracovává chyby. Iteruje prostřednictvím aktualizací, kontroluje platné volby a odesílá jednotlivé bloky odpovědí jako řádky JSON. Pokud dojde k chybě, zaprotokoluje chybu a odešle klientovi chybovou zprávu JSON a pokračuje ve streamu.

    try:
        async for update in await chat_coroutine:
            if update.choices:
                yield update.choices[0].model_dump_json() + "\n"
        except Exception as e:
            current_app.logger.error(e)
            yield json.dumps({"error": str(e)}, ensure_ascii=False) + "\n"
    
    return Response(response_stream())
    

Zpracování obsahu logického úsudku

I když tradiční jazykové modely poskytují pouze konečné výstupy, modely pro logické uvažování, jako je DeepSeek-R1, ukazují své průběžné kroky. Tyto kroky jsou užitečné pro:

  • Řešení složitých problémů
  • Provádění matematických výpočtů
  • Zpracování vícestupňového logického uvažování
  • Provádění transparentních rozhodnutí

Obslužná rutina události submit zpracovává streamovací odpověď index.html na front-endu. Tento přístup vám umožní přístup k poslednímu výstupu a zobrazit kroky odůvodnění modelu.

Front-end používá ReadableStream ke zpracování streamovaných odpovědí z back-endu. Odděluje obsah odůvodnění od běžného obsahu, zobrazuje důvod v rozbalitelné části a konečnou odpověď v hlavní oblasti chatu.

Podrobný rozpis

  1. Zahájení žádosti o streamování

    Tento fragment kódu vytvoří připojení mezi front-endem JavaScriptu a back-endem Pythonu, což umožňuje integraci Azure OpenAI pro DeepSeek-R1 s ověřováním bez klíčů.

    const response = await fetch("/chat/stream", {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify({messages: messages})
    });
    
  2. Inicializujte proměnné

    Následující fragment kódu inicializuje proměnné pro ukládání odpovědí a myšlenek samostatně. Toto oddělení pomáhá efektivně zpracovávat odůvodnění obsahu.

    let answer = "";
    let thoughts = "";    
    
  3. Zpracování každé aktualizace

    Následující fragment kódu asynchronně iteruje bloky odpovědí modelu.

    for await (const event of readNDJSONStream(response.body)) {
    
  4. Detekce a směrování typu obsahu

    Skript zkontroluje, jestli událost obsahuje delta pole. Pokud ano, zpracovává obsah na základě toho, jestli se jedná o obsah zaměřený na uvažování nebo běžný obsah.

    if (!event.delta) {
         continue;
    }
    if (event.delta.reasoning_content) {
         thoughts += event.delta.reasoning_content;
         if (thoughts.trim().length > 0) {
             // Only show thoughts if they are more than just whitespace
             messageDiv.querySelector(".loading-bar").style.display = "none";
             messageDiv.querySelector(".thoughts").style.display = "block";
             messageDiv.querySelector(".thoughts-content").innerHTML = converter.makeHtml(thoughts);
         }
     } else if (event.delta.content) {
         messageDiv.querySelector(".loading-bar").style.display = "none";
         answer += event.delta.content;
         messageDiv.querySelector(".answer-content").innerHTML = converter.makeHtml(answer);
     }
    
    • Pokud je typ obsahu reasoning_content, obsah se přidá do thoughts a zobrazí se v oddílu .thoughts-content.
    • Pokud je typ obsahu content, obsah se přidá do answer a zobrazí se v oddílu .answer-content.
    • Jakmile se obsah začne streamovat, .loading-bar se skryje a .thoughts oddíl se zobrazí, pokud jsou nějaké myšlenky.
  5. Zpracování chyb:

    Chyby se zaprotokolují v back-endu a vrátí se klientovi ve formátu JSON.

    except Exception as e:
        current_app.logger.error(e)
        yield json.dumps({"error": str(e)}, ensure_ascii=False) + "\n"
    

    Tento fragment kódu front-endu zobrazí chybovou zprávu v rozhraní chatu.

    messageDiv.scrollIntoView();
    if (event.error) {
        messageDiv.innerHTML = "Error: " + event.error;
    }
    

Vyčištění služby GitHub Codespaces

Odstraňte prostředí Codespaces na GitHubu pro maximální využití vašich bezplatných hodin pro jednotlivé jádro.

Důležité

Další informace o bezplatném úložišti a hodinách procesoru vašeho účtu GitHub najdete v tématu GitHub Codespaces měsíčně zahrnuté úložiště a hodiny procesoru.

  1. Přihlaste se k řídicímu panelu GitHub Codespaces .

  2. Vyhledejte aktivní Codespaces vytvořené z Azure-Samples//deepseek-python úložiště na GitHubu.

  3. Otevřete kontextovou nabídku pro codespace a vyberte Odstranit.

Získání pomoci

Zapište svůj problém do problémů úložiště.

Další kroky