BAML vs Instructor: Strukturerade LLM-utdata
Typsäkra LLM-utdata med BAML och Instructor
När man arbetar med stora språkmodeller (LLM) i produktionsmiljöer är det avgörande att få strukturerade, typsäkra utdata. Två populära ramverk – BAML och Instructor – tar olika tillvägagångssätt för att lösa detta problem.
Denna jämförelse hjälper dig att välja rätt verktyg för dina Python-baserade LLM-applikationer.

Att förstå utmaningarna med strukturerad utdata
LLM:er genererar naturligt ostrukturerad text, men moderna applikationer kräver förutsägbar, tolkbar data. Oavsett om du bygger chattrobotar, pipeline för dataextraktion eller AI-agenter, behöver du JSON-objekt, validerade datatyper och felhantering – inte fritt format text.
Både BAML och Instructor adresserar denna utmaning, men med fundamentalt olika filosofier: BAML använder ett “contract-first”-tillvägagångssätt med kodgenerering, medan Instructor utnyttjar Pythons typesystem med validering vid körning. Om du är intresserad av bredare kontext gällande strukturerade utdata från olika LLM-leverantörer, blir förståelsen av dessa ramverk ännu mer värdefull. För validering, avslag och pytest-fixturer under ramverkslagret, se Validering av strukturerad LLM-utdata i Python som håller.
BAML: Ett domenspecifikt språk för LLM:er
BAML (BoundaryML:s språk) introducerar ett dedikerat DSL (domenspecifikt språk) för att definiera LLM-interaktioner. Du skriver .baml-filer som deklarerar dina prompts, typer och funktioner, och BAML genererar sedan typsäker klientkod för flera språk, inklusive Python.
Nyckelfunktioner i BAML
Typsäkerhet över språk: BAML genererar klienter för Python, TypeScript och Ruby från samma .baml-definitioner, vilket säkerställer konsistens i hela din stack.
Versionshantering för prompts: Dina prompts finns i .baml-filer, vilket gör dem lätta att spåra, granska och testa oberoende av applikationskoden.
Inbyggd testram: BAML inkluderar testverktyg för att validera promptbeteende innan utleverans, vilket fångar problem tidigt i utvecklingsprocessen.
Playground-gränssnitt: BAMLs playground låter dig iterera på prompts visuellt med omedelbar återkoppling, vilket accelererar utvecklingscyklerna.
Exempel på implementering med BAML
# Först, definiera ditt schema i en .baml-fil:
# persona.baml
class Person {
name string
age int
occupation string
skills string[]
}
function ExtractPerson(text: string) -> Person {
client GPT4
prompt #"
Extrahera personinformation från: {{ text }}
Returnera strukturerad data.
"#
}
Den genererade Python-klienten ger typsäker åtkomst:
from baml_client import b
from baml_client.types import Person
# Använd den genererade klienten
text = "John Smith, 34, mjukvaruingenjör kunnig i Python och Go"
result: Person = b.ExtractPerson(text)
print(f"{result.name} är {result.age} år gammal")
print(f"Färdigheter: {', '.join(result.skills)}")
BAMLs tillvägagångssätt lyser när du har flera tjänster som konsumerar samma LLM-kontrakt eller när du behöver starka garantier om datastycken över språkgränserna.
Instructor: Ett Pydantic-nativt Python-ramverk
Instructor tar ett Python-först-tillvägagångssätt och utökar Pydantic-modeller med LLM-funktioner. Det känns naturligt för Python-utvecklare som redan använder Pydantic för validering och typantydningar.
Nyckelfunktioner i Instructor
Ingen boilerplate-kod: Instructor arbetar direkt med dina befintliga Pydantic-modeller med enkla dekoratorer. Ingen kodgenerering eller byggsteg krävs.
Rik validering: Utnyttja Pydantics hela valideringsekosystem – anpassade validerare, fältbegränsningar, beräknade fält och komplexa nästlade strukturer.
Stöd för flera leverantörer: Fungerar sömlöst med OpenAI, Anthropic, Google och Ollama genom ett enhetligt gränssnitt.
Stöd för strömning: Förstklassigt stöd för strömmade svar med inkrementella Pydantic-modelluppdateringar.
Logik för omförsök: Inbyggda mekanismer för omförsök med exponentiell backoff och felåterhämtning baserad på validerare.
Exempel på implementering med Instructor
from pydantic import BaseModel, Field
from instructor import from_openai
from openai import OpenAI
# Definiera din Pydantic-modell
class Person(BaseModel):
name: str = Field(description="Personens fullständiga namn")
age: int = Field(ge=0, le=120, description="Ålder i år")
occupation: str
skills: list[str] = Field(description="Lista över yrkesmässiga färdigheter")
# Patcha OpenAI-klienten
client = from_openai(OpenAI())
# Extrahera strukturerad data
text = "John Smith, 34, mjukvaruingenjör kunnig i Python och Go"
result = client.chat.completions.create(
model="gpt-4",
response_model=Person,
messages=[
{"role": "user", "content": f"Extrahera personinfo: {text}"}
]
)
print(f"{result.name} är {result.age} år gammal")
print(f"Färdigheter: {', '.join(result.skills)}")
Instructors styrka ligger i dess enkelhet och integration med Pythons ekosystem. Om du redan använder Pydantic är inlärningskurvan minimal. För utvecklare som är nya till Python eller behöver en snabb referens för Python-specifika mönster, ger vår Python-minnesanteckning hjälpsamma påminnelser om syntaxen tillsammans med dessa ramverk.
Detaljerad jämförelse: BAML vs Instructor
Utvecklingsupplevelse
BAML kräver ett ytterligare byggsteg och verktygsinställning. Du skriver .baml-filer, kör generatorn och importerar sedan den genererade koden. Detta skapar en tydlig separation mellan prompt-ingenjörskap och applikationslogik, vilket kan vara fördelaktigt för större team.
Instructor har noll inställningsfriktion – pip-installera och du är redo. Dina prompts finns tillsammans med din kod, vilket gör snabb iteration enklare för mindre projekt eller prototyper.
Typsäkerhet och validering
BAML ger typkontroll vid kompileringstid i den genererade koden. Din IDE vet exakt vilka fält som är tillgängliga innan du kör något. Cross-språkskonsistens är garanterad eftersom samma .baml-fil genererar klienter för alla supportede språk.
Instructor erbjuder validering vid körning genom Pydantic. medan Python-typantydningar ger IDE-stöd, dyker fel upp under exekvering. Detta är standard för Python men innebär mindre statisk garanti än BAMLs genererade kod.
Arbeta med lokala LLM:er
Båda ramverken stödjer lokala modeller, vilket är avgörande för integritet, kostnadskontroll och offline-utveckling. När du använder Ollama eller andra lokala LLM-leverantörer behåller du samma fördelar med strukturerad utdata utan beroende av externa API:er. För en djupare analys av att begränsa LLM:er med strukturerad utdata med Ollama, Qwen3 och Python eller Go, ger dessa ramverk produktionsklara abstraktioner över de lägre nivå-API:erna.
BAML ansluter till Ollama genom att konfigurera klienten i din .baml-fil:
# I din .baml-fil:
client OllamaLocal {
provider ollama
options {
model "llama2"
base_url "http://localhost:11434"
}
}
Instructor arbetar med Ollama genom OpenAI-kompatibla API:et:
from openai import OpenAI
from instructor import from_openai
client = from_openai(OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama" # dummy key
))
Observera att när du arbetar med lokala modeller bör du vara medveten om potentiella problem med strukturerad utdata hos Ollama och GPT-OSS-modeller, eftersom inte alla modeller hanterar strukturerad utdata med samma tillförlitlighet.
Felhantering och omförsök
BAML hanterar omförsök på ramverksnivå med konfigurerbara strategier. Fel i schemavalidering utlöser automatisk omfrågan med felkontext.
Instructor erbjuder dekorativ logik för omförsök med krokar för anpassat beteende. Du kan definiera validerare som utlöser omförsök med modifierade prompts:
from instructor import patch
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3))
def extract_with_retry(text: str) -> Person:
return client.chat.completions.create(
model="gpt-4",
response_model=Person,
messages=[{"role": "user", "content": text}]
)
Testning och observabilitet
BAML inkluderar en testram där du kan skriva testfall direkt i .baml-filer, vilket validerar promptbeteende över olika indata. Playgrounden ger visuell felsökning.
Instructor integreras med standard Python-testramverk. Du kan använda pytest-fixturer, mock-bibliotek och assertionshjälpmedel precis som med vilken Python-kod som helst.
Prestandahänsyn
Prestanda vid körning är jämförbar – båda ramverken gör slutligen samma LLM-API-anrop. Överhållen för validering och tolkning är försumbar i jämförelse med nätverkslatens och modellens inferenstid.
Utvecklingshastighet skiljer sig markant:
- BAMLs kodgenerering innebär bättre autocomplete och tidigare felupptäckt men kräver ett byggsteg
- Instructors dekorator-tilvägagångssätt innebär snabbare iteration men felupptäckt vid körning
För produktionssystem som bearbetar miljoner förfrågningar hanterar båda ramverken belastningen lika väl. Ditt val beror mer på preferenser för arbetsflöde vid utveckling än på prestandakarakteristika.
När du ska välja BAML
Välj BAML när du behöver:
- Stöd för flera språk: Åtkomst till samma LLM-kontrakt från Python-, TypeScript- och Ruby-tjänster
- Contract-first-utveckling: API-liknande utveckling där LLM-gränssnitt designas innan implementering
- Samarbete i team: Separera prompt-ingenjörskap från applikationsutveckling
- Starka typgarantier: Kompileringstidskontroller över hela din stack
- Visuell prompt-utveckling: Playground-drivna iterationer på prompts
När du ska välja Instructor
Välj Instructor när du vill:
- Projekt endast i Python: Inget behov av konsistens över språk
- Snabb prototypering: Minimal inställning för att få strukturerad utdata att fungera
- Pydantic-integration: Utnyttja befintliga Pydantic-modeller och validerare
- Enkel leverans: Inga byggsteg eller genererad kod att hantera
- Rikt Python-ekosystem: Använda Python-specifika bibliotek och mönster
Kombinera tillvägagångssätt
Vissa projekt gynnas av att använda båda ramverken. Till exempel kan du använda BAML för kundvända API:er som behöver klienter över flera språk, medan du använder Instructor för interna Python-tjänster som behöver snabb iteration.
Du kan också gå över mellan ramverk när ditt projekt mognar – starta med Instructor för snabb validering, och flytta sedan till BAML när du behöver bredare språkstöd eller striktare kontrakt.
Verkliga användningsfall
Pipeline för dataextraktion (BAML)
Ett dokumenthanteringssystem använder BAML för att extrahera strukturerad data från fakturor, kontrakt och kvitton. .baml-definitionerna fungerar som kontrakt mellan ML-teamet och backend-tjänsterna, med TypeScript-klienter för webbpanelen och Python-klienter för batchbearbetning.
Kundsupportrobot (Instructor)
En supportrobot använder Instructor för att klassificera ärenden, extrahera användarintentioner och generera svar. Teamet itererar snabbt på prompts med Pydantic-modeller, med validerare som säkerställer att extraherade telefonnummer, e-postadresser och ärendenummer uppfyller formatkrav.
Multimodal AI-agent (Båda)
Ett AI-agentsystem använder BAML för kärnkontrakt för kommunikation mellan agenter, vilket säkerställer typsäkerhet över det distribuerade systemet, medan individuella agenter använder Instructor internt för flexibel, Python-nativ bearbetning av användarinput. Liknande mönster gäller när man bygger MCP-servrar i Python, där strukturerad utdata möjliggör pålitlig verktygsintegration med AI-assistenter.
Migrations- och integrationsvägar
Om du redan använder grundläggande JSON-tolknings med LLM:er erbjuder båda ramverken raka migrationsvägar:
Från JSON till BAML: Konvertera dina JSON-scheman till BAML-typdefinitioner, flytta prompts till .baml-filer, generera klienter och ersätt manuell tolkning med genererade typer.
Från JSON till Instructor: Lägg till Pydantic-modeller som matchar din JSON-struktur, installera instructor, patcha din OpenAI-klient och ersätt JSON-tolknings med response_model-parametrar.
Båda migrationerna kan vara inkrementella – du behöver inte konvertera hela din kodbas på en gång.
Framtidsutsikter och gemenskap
Båda ramverken utvecklas aktivt med starka gemenskaper:
BAML (BoundaryML) fokuserar på att utöka språkstöd, förbättra playgrounden och förbättra testmöjligheter. Det kommersiella stödet tyder på långsiktig stabilitet.
Instructor upprätthåller en stark närvaro som open source med frekventa uppdateringar, omfattande dokumentation och växande adoption. Projektet är välunderhållt av Jason Liu och medverkande.
Slutsats
BAML och Instructor representerar två utmärkta men distinkta tillvägagångssätt för strukturerad LLM-utdata. BAMLs contract-first, multi-språkfilosofi passar team som bygger distribuerade system med strikta typkrav. Instructors Python-nativa, Pydantic-baserade tillvägagångssätt passar snabb utveckling och Python-centrerade stackar.
Varken den ena eller den andra är universellt bättre – ditt val beror på ditt teams storlek, språkpreferenser, utvecklingsarbetsflöde och krav på typsäkerhet. Många team kommer att upptäcka att att börja med Instructor för prototypering, och sedan anta BAML för produktionens multi-service-arkitekturer, erbjuder det bästa av båda världar.
Användbara länkar
Relaterade artiklar på denna webbplats
- Begränsa LLM:er med strukturerad utdata: Ollama, Qwen3 & Python eller Go
- Jämförelse av strukturerad utdata över populära LLM-leverantörer - OpenAI, Gemini, Anthropic, Mistral och AWS Bedrock
- Ollama GPT-OSS-strukturerade utdata-problem
- Bygg MCP-servrar i Python: WebSearch & Scrape
- Python-minnesanteckning
- Ollama-minnesanteckning