Automating Data Ingestion with a RAG Flywheel Zalando's Supply Operations team built an LLM-powered schema-mapping system using a Retrieval-Augmented Generation (RAG) Flywheel on AWS Bedrock to automate mapping of supplier data schemas ranging from 10-60 columns per sheet into an internal target schema of over 55 columns. The system uses Amazon Titan Text Embeddings V2 to generate 1024-dimensional vectors for semantic search and a generative model such as Anthropic Claude Sonnet or Gemini for reasoning, with the API acting as the final decision boundary. Zalando hardcodes temperature to 0.0 and requires tool-use output containing sourceColumn, targetColumn, reasoning, and confidenceScore, with every suggestion validated and reviewed by a human. Automating Data Ingestion with a RAG Flywheel Automating schema mapping for diverse supplier data using a RAG Flywheel and LLMs. The Problem: The Schema Mapping Bottleneck ¶ the-problem-the-schema-mapping-bottleneck At Zalando, our Supply Operations team manages a vast array of supplier offers. Each supplier provides their data in different formats, structures, and schemas. This diversity creates a significant challenge for the data ingestion processes, as they need to map these varying schemas into a unified format that our systems can understand and process efficiently. For every uploaded file, operations specialists must manually map the highly diverse schemas source headers/columns , ranging from 10-60 columns per sheet per workbook, with unpredictable variations in header naming conventions like "Art.-Nr.", "Article Number", "SKU", or "Farbe" color in German to our strictly defined internal target schema of over 55 columns for example, SKU , Color Code , and Color Name . Traditionally, automating this type of schema matching relied heavily on hardcoded rules, regular expressions, or Levenshtein distance-based fuzzy matching. However, these methods often fall short when dealing with the high variability and complexity of real-world data. The semantic meaning of a column such as Retail Price might appear under different names like UVP , Price , or MSRP . Since these legacy engines lack semantic understanding of the data, they tend not to scale with the growing diversity of supplier data and require continuous manual maintenance from engineers every time a new supplier is onboarded or an existing supplier changes its data format. To eliminate this operational bottleneck, we needed a system capable of understanding the semantic meaning of the data and generating smart mapping suggestions. In this post, we explore how we built an LLM-powered continuous learning loop using a Retrieval-Augmented Generation RAG Flywheel to automate the schema mapping process. We also explain how we constrained the model output and integrated pgvector to produce safer and more historically consistent results. Context Segregation & Controlled Output ¶ context-segregation-controlled-output To build the system within our infrastructure constraints, we rely on AWS Bedrock to host our external AI dependencies. We split the workload across 2 distinct components: Amazon Titan Text Embeddings V2 to generate 1024-dimensional vectors for semantic search, and a generative model like Anthropic Claude Sonnet or Gemini to execute the logical reasoning and deductions. The API acts as the central orchestrator, isolating the static internal target schemas from the dynamic, historically embedded supplier data and mappings before sending them to the LLM. Enforcing Safety with Tool Use ¶ enforcing-safety-with-tool-use LLMs are not deterministic: they can produce different outputs and hallucinate. Our goal is therefore to constrain their behavior and keep the API as the final decision boundary. We implement two primary constraints at the API level: 1. Zero Temperature : We hardcode the temperature parameter to 0.0 . Schema matching benefits from repeatable reference lookups, and a higher temperature can introduce unnecessary variation. 2. Tool Use : We require the model to return a fixed structure containing sourceColumn , targetColumn , reasoning , and confidenceScore . Tool use constrains the response shape, but it does not guarantee that the semantic mapping is correct; that is why every suggestion is validated and reviewed by a human. API as the Gatekeeper ¶ api-as-the-gatekeeper Even with the above constraints, we treat the LLM output as untrusted until verified. Before any LLM-generated suggestion reaches users or the database, the API performs synchronous validation checks that catch model misbehavior. These checks include: - Unknown Source Column : Rejecting any source column that is not present in the uploaded file. - Unknown Target Column : Rejecting any target column that is not part of the internal target schema. - Missing Source Column : Guaranteeing full coverage of all source columns from the uploaded file. Validation in Practice ¶ validation-in-practice The validation process applies a predictable sequence of checks to the raw mappings generated by the LLM. 1. Prepare Verification Sets : The API constructs sets of known source and target columns from the uploaded file and the internal schema, respectively. 2. Iterate and Validate : Loop through each mapping suggestion: - If a source column is not in the known source set, reject the suggestion. - If a target column is not in the known target set, reject the suggestion. 3. Verify Coverage and Stable Ordering : Finally, iterate through the known source columns to ensure that each one has a corresponding mapping, and reorder the suggestions to match the original file structure. Here is a simplified TypeScript implementation of the validation logic: function validateGeneratedMappings mappings: MappingItem , sourceColumns: SourceColumn , targetColumns: TargetColumnDefinition : MappingItem { const expectedSet = new Set sourceColumns.map sc = sc.name ; const allowedTargets = new Set targetColumns.map tc = tc.name ; const bySource = new Map