helgesverre/extractor
Extractor is a Laravel package that uses OpenAI to pull structured data out of images, PDFs, emails, Word docs, and web pages. Define fields, get arrays or Spatie data objects back—no custom parsing logic needed.
Architecture fit
Extractor, Text), one abstract Extractor class, and a config file. It layers on top of openai-php/laravel rather than reimplementing an HTTP client, which keeps the abstraction shallow and replaceable.laravel-data hydration. For a Laravel codebase already comfortable with facades and DTOs, the mental model maps cleanly.Text helper class plus direct OpenAI::chat() calls with a JSON schema instruction — an estimated 2-5 engineering days per extractor in use. This materially de-risks the "buy" decision.Integration feasibility
composer require, publish extractor-config, publish the OpenAI provider config, set OPENAI_API_KEY. No database migrations, no service provider gymnastics, no queue topology assumptions.OPENAI_BASE_URI (Ollama, Together, Groq) and a documented Azure override that rebinds ClientContract in AppServiceProvider. That is enough to support self-hosted inference for PII-sensitive workflows and to avoid single-vendor exposure on the model side.prompt() and expectedOutputKey(), register with Extractor::extend(). Straightforward for a mid-level Laravel engineer.composer.json and the repo before committing.Technical risk
Text::web($url) fetches arbitrary URLs over HTTP. If any user-supplied URL reaches that method, an allowlist, scheme restriction, and response-size cap are mandatory.Text::word unzips and XML-parses uploads; Text::pdf uses smalot/pdfparser. Both process untrusted binaries. Zip-bomb and XXE exposure need review, and parsing should occur in an isolated worker.Engine constants (GPT_4O_MINI, GPT_4O). OpenAI deprecations will silently break these; pin, test, and own the mapping.Key questions
maxTokens truncation?Stack fit
laravel-data only if the team already uses it — the package's DTO return mode is convenient but shallow, and the DTO cannot enforce correctness the model didn't produce..env on disk; the Azure binding example references env() directly and should be refactored to config().Migration path
Compatibility
composer.json; do not float. Treat upgrades as change-managed events with a fixed evaluation corpus.AppServiceProvider.Sequencing
extractions table persisting raw model output, parsed payload, model ID, prompt version, token counts, and latency.fields() API) for any document type with volume or business criticality.Maintenance
openai-php calls) current.Support
Scaling
Failure modes
maxTokens), hallucinated fields, and empty results indistinguishable from "no data present."Text::web; parser exploits on crafted uploads.OPENAI_BASE_URI as the mitigation path.Ramp-up
How can I help you explore Laravel packages today?