[{"content":"","date":null,"permalink":"https://ntwk.es/ca/categories/ai/","section":"Categories","summary":"","title":"AI"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/ai/","section":"Tags","summary":"","title":"AI"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/posts/","section":"Articles del Blog Tecnològic","summary":"","title":"Articles del Blog Tecnològic"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/categories/","section":"Categories","summary":"","title":"Categories"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/crm/","section":"Tags","summary":"","title":"CRM"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/categories/data-engineering/","section":"Categories","summary":"","title":"Data Engineering"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/dataengineering/","section":"Tags","summary":"","title":"DataEngineering"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/embeddings/","section":"Tags","summary":"","title":"Embeddings"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/enterpriseai/","section":"Tags","summary":"","title":"EnterpriseAI"},{"content":"Feeding the Machine Right: CRM Data Ingestion for AI Systems #How to preprocess and architect heterogeneous business data for vector databases, semantic search, and AI agents — and why mastering this is becoming one of the most valuable skills in enterprise AI.\n1. The Hidden Problem Nobody Talks About #If your AI system gives shallow, unreliable, or contextually blind answers about your customers, your first instinct is probably to blame the model. Swap the LLM, tune the embeddings, adjust the retrieval parameters. Most teams go through several cycles of this before arriving at an uncomfortable truth: the model was never the problem.\n\u0026ldquo;Garbage in, garbage out\u0026rdquo; is the oldest principle in computing. In the AI era, it hasn\u0026rsquo;t changed — it\u0026rsquo;s just better dressed. Teams now feed garbage into systems sophisticated enough to sound confident about it, which makes the problem harder to spot and more expensive to fix.\nThe reality observed across enterprise AI projects is consistent: the majority of underperforming RAG systems, AI agents, and semantic search implementations fail not because of model choice or vector database configuration, but because of how the source data was prepared — or wasn\u0026rsquo;t. Your embedding model is probably fine. Your documents are the problem.\nCRM data makes this especially treacherous. Unlike a PDF corpus or a product catalogue, CRM data isn\u0026rsquo;t flat — it has a shape. A contact belongs to a company, holds a role, carries a communication history, links to open tasks, and sits somewhere in a commercial pipeline. That shape is the meaning. When you flatten it into tabular rows or key-value pairs, you don\u0026rsquo;t just lose formatting — you destroy the relational context that makes the data intelligible.\nThis is what makes CRM ingestion one of the hardest data preparation problems in enterprise AI. It\u0026rsquo;s not a document problem. It\u0026rsquo;s not a tabular data problem. It\u0026rsquo;s a living relational graph problem — and most ingestion pipelines treat it like neither.\nThere\u0026rsquo;s also a human gap worth naming early. Companies are investing in AI engineers and vector infrastructure, but almost none are investing in people who know how to bridge complex business data and AI systems. That gap is quietly responsible for a large share of disappointing enterprise AI projects — and it is, increasingly, a significant professional opportunity.\nThis article is about closing that gap. We\u0026rsquo;ll dissect the generic structure of CRM data, identify where ingestion goes wrong, and build up a clear architecture for preprocessing and structuring heterogeneous business data so that AI systems — agents, semantic search, automated workflows — can actually reason with it.\n2. How CRM Data Is Actually Shaped #Before you can design an ingestion architecture, you need an accurate mental model of what CRM data actually is. Not as a database schema — as a living information structure.\nAt its core, every CRM revolves around two root entities: Companies and Contacts. Everything else either describes them or records what happened between them and your organisation.\nCOMPANIES └── CONTACTS (via typed relationships) ├── COMMUNICATIONS (emails · calls · meetings) ├── TASKS \u0026amp; CALENDAR └── COMMERCIAL PIPELINE (leads → offers → sales) But this hierarchy is already a simplification. The reality is a web, not a tree.\nThe root entities and their relationships\nA Company is more than a name and an address. It carries sector, size, segment, location, status — and it can be related to other companies (subsidiaries, partners, parent groups).\nA Contact is a person, but their connection to a company is itself a rich object. It has a type (employee, advisor, partner), a role, a department, a seniority level — and critically, it has a time dimension. A contact may have been a procurement manager at a company from 2019 to 2022, and a director somewhere else since then. That temporal typing is business-critical context that flat ingestion almost always discards.\nContacts also carry multiplicity: one person may have two work emails, a personal address, three phone numbers, and profiles on LinkedIn, Twitter, and WhatsApp. These aren\u0026rsquo;t just contact details — they\u0026rsquo;re identity anchors that link communications across channels. And like roles, they can be time-scoped: a phone number that was valid last year may not be today.\nThe communications layer\nAbove the entity layer sits a rich layer of interaction records. These are the dynamic, event-based data: things that happened, as opposed to things that are.\nEmails, calls, and meetings are all communications — but they are not the same shape of data:\nAn email has a sender, one or more recipients, a subject, a body, attachments, and a direction (inbound or outbound). It can link multiple contacts across different companies in a single record. A call has a direction, a duration, a timestamp, and typically a short outcome note. Its \u0026ldquo;content\u0026rdquo; is often sparse — a summary rather than a transcript. A meeting has attendees (potentially many), a scheduled time, an agenda, and sometimes minutes or outcomes. It is inherently multi-party. This asymmetry matters enormously for ingestion. Treating these three as interchangeable \u0026ldquo;communication records\u0026rdquo; loses the structural differences that make each type semantically distinct.\nTasks and calendar: the intentions layer\nIf communications record what happened, tasks and calendar events record what is supposed to happen. They are the intentions and commitments layer of the CRM.\nA task is assigned to someone, has a type (follow-up call, send proposal, escalate issue), a creation date, a due date, a status, and a description. A calendar event is scheduled, involves specific participants, and occupies a defined time slot.\nBoth are linked to contacts and companies — and both carry their own temporal weight. An overdue task tells a very different story than a completed one. An upcoming meeting with a key contact is strategically relevant in a way that a past one may not be.\nThe commercial pipeline\nThe pipeline is where relational complexity peaks. A lead represents early-stage interest — qualified or unqualified, with a source and a probability. As it progresses it becomes an opportunity, then an offer.\nAn offer is a formal commercial document: it has a value, a currency, a status (draft, sent, negotiation, won, lost), and dates. It is directed at a contact, associated with a company, and linked to the history of communications and tasks that led to it.\nFor the purposes of ingestion, an offer is best treated as a self-contained object — rich enough to carry its commercial context without requiring its full relational history to be meaningful.\nThe dark matter: free-text fields\nScattered throughout every CRM are notes, comments, descriptions, and memo fields. These are the dark matter of business data — unstructured, inconsistent, and almost always ignored by ingestion pipelines.\nThey are also often the most informationally dense content in the entire system. A salesperson\u0026rsquo;s note on a contact — \u0026ldquo;prefers not to be called on Mondays, very price-sensitive, key decision-maker despite junior title\u0026rdquo; — contains strategic intelligence that no structured field can capture.\nAny serious ingestion architecture must have a strategy for this layer.\nWhat this map reveals is that CRM data is neither a document collection nor a relational table. It is a heterogeneous, temporally-aware, multi-entity graph — and the ingestion architecture must reflect that reality.\n3. The Four Most Common Ingestion Mistakes #Most CRM ingestion failures don\u0026rsquo;t announce themselves. The pipeline runs, the vectors are written, the system responds. It just responds poorly — with shallow answers, missed context, and retrieval that feels random. The mistakes that cause this are surprisingly consistent across teams and organisations.\nMistake 1: Tabular Dumping\nThe most common mistake is also the most understandable. Your CRM data lives in a relational database. You export it. You get tables. You feed the tables.\nThe result is vectors built from rows like:\nid: 1042 | name: John Smith | company: Acme Corp | email: john@acme.com | status: active | created: 2021-03-01 Each row becomes one vector. The embedding model receives a string that reads like a spreadsheet cell — because it is one. There is no narrative, no context, no relationship to anything else. The vector captures the statistical pattern of that string, which is close to nothing meaningful.\nTabular dumping treats a relational graph as if it were a flat file. The structure that gives the data its meaning — who this person is, what they\u0026rsquo;ve said, what they\u0026rsquo;re worth to the business — is entirely absent.\nMistake 2: Key-Value Feeding\nA variation of the above, and equally widespread. Instead of raw CSV rows, teams serialize their records into JSON or property strings and embed those:\n{name: \u0026#34;John Smith\u0026#34;, role: \u0026#34;buyer\u0026#34;, company: \u0026#34;Acme Corp\u0026#34;, phone: \u0026#34;+34-600-123456\u0026#34;} This feels more structured — and it is, for a database. But embedding models are not databases. They are trained on natural language. They do not parse JSON syntax. They do not understand that name: and role: are field labels. What they receive is a token stream that bears no resemblance to how humans describe a person, a relationship, or a business situation.\nThe vectors produced are geometrically incoherent — scattered in embedding space in ways that make meaningful similarity search nearly impossible.\nMistake 3: No Metadata Glue\nEven teams that produce reasonably structured text for their vectors often neglect the payload — the structured metadata that should travel alongside every vector in the database.\nWithout metadata, a vector is an orphan. You can find it via similarity search, but you cannot:\nFilter results by company, contact, date range, or entity type Link it back to its source record in the relational database Assemble multi-entity context for an agent (e.g. \u0026ldquo;give me all communications and open tasks for this contact\u0026rdquo;) Understand what type of thing you\u0026rsquo;ve retrieved — is this an email? A task? An offer? Metadata is the connective tissue of a semantic index. Skipping it produces a vector database that can only do one thing — global similarity search — and does it without any ability to scope, filter, or join. That is a fraction of what the architecture is capable of.\nMistake 4: Raw Concatenation Instead of Semantic Documents\nThe subtlest and most damaging mistake. Teams aware of the previous three problems often arrive at a solution that looks right but isn\u0026rsquo;t: they concatenate all the fields of a record into a single text string and embed that.\n\u0026#34;John Smith buyer Acme Corp john@acme.com +34-600-123456 Barcelona active 2021-03-01\u0026#34; Or slightly better:\n\u0026#34;Name: John Smith. Role: buyer. Company: Acme Corp. Email: john@acme.com. City: Barcelona.\u0026#34; This is closer — but it still fails. Embedding models perform best on text that carries semantic intent: text that means something the way a sentence means something. A list of field-value pairs has syntactic structure but minimal semantic density. It doesn\u0026rsquo;t tell the model who John Smith is, what his relationship to Acme Corp means, or why he matters.\nThe gap between \u0026ldquo;Name: John Smith. Role: buyer.\u0026rdquo; and \u0026ldquo;John Smith is the senior buyer at Acme Corp, responsible for procurement decisions in the logistics division\u0026rdquo; is not cosmetic. In embedding space, these two representations land in very different places — and only one of them clusters meaningfully with related concepts like purchasing authority, vendor relationships, and contract negotiations.\nMistake 5: Ignoring Free-Text and Over- or Under-Fragmenting\nTwo further mistakes often accompany the ones above.\nThe first is systematically ignoring the free-text fields — notes, comments, call summaries, meeting minutes — that live throughout a CRM. These are treated as too messy, too inconsistent, too hard to process. In reality they are frequently the highest signal content in the entire system. A salesperson\u0026rsquo;s note carries intent, nuance, and strategic context that no structured field can encode.\nThe second is getting the granularity wrong in either direction. Over-fragmentation — creating one vector per field, embedding phone numbers and email addresses in isolation — produces meaningless atomic units. Under-fragmentation — stuffing an entire company record with all its contacts, communications, and history into a single document — produces bloated, unfocused vectors that retrieve everything and nothing at once.\nBoth extremes destroy the semantic coherence that makes retrieval useful.\nThe common thread\nEvery one of these mistakes shares a root cause: the ingestion was designed around the convenience of the source data, not around the needs of the AI system consuming it. CRM data was structured for human operators and relational queries. Before it can serve an AI, it must be deliberately restructured — transformed from records into knowledge. That transformation is the subject of the rest of this article.\n4. The Principle of Semantic Granularity #If there is one principle that governs everything in CRM data ingestion, it is this: one semantic idea, one document.\nA document, in this context, is not a file. It is the unit of meaning you present to the embedding model — the coherent, focused chunk of text that becomes one vector in your index. Getting this unit right is the single most impactful decision in your entire ingestion architecture.\nWhy focus matters\nEmbedding models map text into a geometric space where similar meanings cluster together. That geometry only works when each input carries a single, coherent semantic signal. When you mix concerns — stuffing a contact\u0026rsquo;s identity, their full email history, three open tasks, and an offer into one document — the resulting vector is pulled in too many directions at once. It ends up representing everything vaguely rather than anything precisely. Retrieval suffers accordingly.\nThe entity type itself tells you what the right unit is. CRM data splits naturally into two kinds of things: static entities — things that are (companies, contacts) — and dynamic entities — things that happened (emails, calls, tasks, offers). These two kinds require different document shapes. A contact document describes a person and their context. An email document describes an event. Treating them the same way is a category error.\nThe unit of retrieval\nA practical way to find the right granularity: ask what an agent or a search query would want to get back. If the answer is \u0026ldquo;everything about this person\u0026rdquo;, the unit is the contact. If the answer is \u0026ldquo;the email where pricing was discussed\u0026rdquo;, the unit is the individual email. Design your documents around the retrieval use case, not around the source schema.\nThis leads to a clean mapping:\nEntity Granularity Company One document per company Contact One document per contact Email One document per email Call One document per call Meeting One document per meeting Task One document per task Offer One document per offer The multi-value collapse rule\nA contact may have five phone numbers, three email addresses, and profiles on four social networks. These should not become separate documents — they are attributes of a single entity, not independent semantic units. Collapse all of them into the contact document\u0026rsquo;s text and carry them as arrays in the metadata payload. Embedding a phone number in isolation produces a vector that means nothing to anyone.\nRollup documents\nGranular documents are essential for precise retrieval. But AI agents often need a broader view — a 360° summary of a company or contact to orient themselves before diving into specifics. For this, introduce a second document type: the rollup.\nA rollup is a synthetically generated summary, produced periodically or on data change, that condenses the key facts about an entity into one coherent paragraph: who the company is, who the main contacts are, what the recent communication has been, what is commercially open. It sits alongside the granular documents in the vector index — not replacing them, but serving as a high-quality entry point for context assembly.\nThe one-paragraph test\nWhen in doubt about whether a document is correctly scoped, apply this test: what would a well-informed human write about this entity in one paragraph? If the answer flows naturally, the scope is right. If it either feels like a one-liner (too narrow) or requires multiple paragraphs to cover the basics (too wide), adjust.\nGranularity in embedding is like focus in photography. Too wide, and nothing is sharp. Too close, and you lose all context. The right focal length is the one that makes the subject clear — and that focal length is different for a company, a contact, an email, and an offer. Getting it right for each entity type is the craft at the centre of this discipline.\n5. Architecting the Ingestion Pipeline #With the right granularity defined, the next question is structural: how do you physically organise the data that flows into your ingestion pipeline? This section lays out the architecture — from the shape of a single document to the division of responsibility across your storage infrastructure.\nThe universal document unit\nEvery ingestion record, regardless of entity type, follows the same three-field structure:\n{ \u0026#34;id\u0026#34;: \u0026#34;contact_042\u0026#34;, \u0026#34;text\u0026#34;: \u0026#34;John Smith is the senior buyer at Acme Corp...\u0026#34;, \u0026#34;metadata\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;contact\u0026#34;, \u0026#34;company_id\u0026#34;: \u0026#34;001\u0026#34;, ... } } id — a unique, stable identifier scoped to entity type. Never reuse IDs across types. text — the natural-language narrative that gets embedded. This is the only field the model sees. metadata — the structured payload that travels with the vector. Never embedded, always queryable. This three-field contract is the foundation everything else builds on.\nCrafting the text field: narrative templates\nThe text field is not generated — it is engineered. Each entity type gets its own prose template, designed to read as natural language and omit null fields entirely.\nA contact template might produce:\n\u0026ldquo;John Smith is the senior buyer at Acme Corp, responsible for procurement in the logistics division. Reachable at john@acme.com and +34-600-123456. Active relationship since March 2021. Prefers email contact. Key decision-maker for software acquisitions.\u0026rdquo;\nAn email template might produce:\n\u0026ldquo;Inbound email from John Smith (Acme Corp) on 14 September 2024, subject: Contract renewal Q4. Raised concerns about pricing on the logistics module, requested a revised proposal before end of September.\u0026rdquo;\nThe template pulls from structured fields for the skeleton and folds in free-text notes as the final sentence — capturing the dark matter without losing the structure. Any field that is null is simply omitted. Never write \u0026ldquo;phone: null.\u0026rdquo;\nThe metadata payload: structure that enables filtering\nThe metadata object carries everything the text field does not — in structured, queryable form:\n{ \u0026#34;type\u0026#34;: \u0026#34;contact\u0026#34;, \u0026#34;company_id\u0026#34;: \u0026#34;001\u0026#34;, \u0026#34;contact_id\u0026#34;: \u0026#34;042\u0026#34;, \u0026#34;segment\u0026#34;: \u0026#34;enterprise\u0026#34;, \u0026#34;date\u0026#34;: \u0026#34;2021-03-01\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;active\u0026#34; } This payload is what makes your vector index intelligent rather than merely searchable. It enables queries like: \u0026ldquo;find semantically similar contacts, but only within enterprise accounts, active in the last 12 months.\u0026rdquo; Semantic similarity alone cannot do this. Metadata payload combined with vector search can.\nEvery document must carry at minimum: entity type, its own ID, and the IDs of its parent entities (company_id, contact_id where applicable).\nThe two-database architecture\nThe ingestion architecture rests on a clean division of responsibility between two systems:\n┌─────────────────────┐ │ SOURCE CRM / DB │ └──────────┬──────────┘ │ ┌──────────▼──────────┐ │ INGESTION PIPELINE │ │ (transform + enrich)│ └────────┬────────────┘ │ ┌──────────────┴──────────────┐ │ │ ┌──────────▼──────────┐ ┌────────────▼────────────┐ │ VECTOR DB │ │ RELATIONAL DB │ │ (Qdrant / similar) │ │ (PostgreSQL / similar) │ │ │ │ │ │ • Vectors │ │ • Full records │ │ • Metadata payload │ │ • Relational joins │ │ • Semantic search │ │ • Source of truth │ │ • Filtered retrieval│ │ • Audit / history │ └──────────────────────┘ └──────────────────────────┘ The relational database is the source of truth — it holds the full, structured records and handles all relational queries. The vector database is the semantic index — it holds vectors and metadata payloads, and handles similarity search and filtered retrieval. Neither replaces the other.\nThe bridge between them is the shared entity ID. Every vector point in Qdrant references a record in PostgreSQL. When retrieval returns a vector, the ID in its payload is used to fetch the full record from the relational store.\nJSONL as the ingestion format\nThe practical format for passing data to your embedding pipeline is JSONL — one JSON object per line, one line per document:\n{\u0026#34;id\u0026#34;:\u0026#34;contact_042\u0026#34;,\u0026#34;text\u0026#34;:\u0026#34;John Smith is the senior buyer...\u0026#34;,\u0026#34;metadata\u0026#34;:{...}} {\u0026#34;id\u0026#34;:\u0026#34;email_1847\u0026#34;,\u0026#34;text\u0026#34;:\u0026#34;Inbound email from John Smith...\u0026#34;,\u0026#34;metadata\u0026#34;:{...}} JSONL streams efficiently, requires no loading of the full file into memory, and maps directly to one vector write per line. Batch your files by entity type — one file per entity — so that re-ingestion after a schema change or model update can be scoped to only the affected type without reprocessing everything.\nRe-ingestion should be triggered by three events: a record update in the source CRM, a change to the narrative template, or a change of embedding model. Build this trigger into your pipeline from the start — retrofitting it later is costly.\n6. The Relational Glue: Making Cross-Entity Retrieval Work #Semantic search finds documents. But real business questions don\u0026rsquo;t live inside single documents — they span entities, time, and relationship types. \u0026ldquo;What is the current state of our relationship with Acme Corp?\u0026rdquo; requires a contact profile, a communication history, open tasks, and the status of active offers. No single vector answers that. The relational glue is what makes the full answer possible.\nThe linking mechanism: shared entity IDs\nThe architecture is simple in principle: every document\u0026rsquo;s metadata payload carries the IDs of its parent entities. An email document carries contact_id and company_id. A task carries the same. An offer does too. These shared IDs are the connective tissue of the semantic index — they allow retrieval to move across entity types without losing the relational thread.\nemail_1847 → { contact_id: \u0026#34;042\u0026#34;, company_id: \u0026#34;001\u0026#34;, type: \u0026#34;email\u0026#34; } task_0291 → { contact_id: \u0026#34;042\u0026#34;, company_id: \u0026#34;001\u0026#34;, type: \u0026#34;task\u0026#34; } offer_0088 → { contact_id: \u0026#34;042\u0026#34;, company_id: \u0026#34;001\u0026#34;, type: \u0026#34;offer\u0026#34; } contact_042 → { company_id: \u0026#34;001\u0026#34;, type: \u0026#34;contact\u0026#34; } Every vector is individually retrievable by semantic similarity, and collectively queryable by entity relationship. The index becomes a graph you can traverse — not just a list you can search.\nCommunications ↔ Contacts: the interaction layer\nAn email is not a simple two-party exchange. It has a sender, multiple recipients, and potentially contacts from different companies in the same thread. Its metadata must reflect this: carry all participant contact IDs, not just the primary one.\nDirection matters too. An inbound email from a contact who hasn\u0026rsquo;t written in six months tells a very different story than an outbound email that went unanswered. The direction field in metadata is not administrative — it is semantically significant. An agent reasoning about relationship health needs to know who initiated contact and when.\nRetrieving a contact\u0026rsquo;s full communication history is then a metadata filter operation: all documents where contact_id = \u0026quot;042\u0026quot; and type IN [email, call, meeting], ordered by date. The semantic index makes this fast and filterable without touching the relational database for every lookup.\nTasks ↔ Contacts: the intentions layer as relationship signal\nTasks are not to-do lists. In the context of AI retrieval, they are intention signals — structured evidence of what your team believes needs to happen next with a given contact or company.\nAn open task of type \u0026ldquo;send revised proposal\u0026rdquo; linked to a contact tells an agent that a commercial conversation is in progress. An overdue task of type \u0026ldquo;follow-up call\u0026rdquo; that is three weeks past its due date signals a relationship at risk. The temporal metadata — creation date, due date, closing date, status — transforms a task from an administrative record into a diagnostic signal.\nWhen assembling context about a contact, tasks should always be retrieved alongside communications. Together they form a timeline of what happened and what was supposed to happen — the two dimensions an agent needs to reason about relationship state.\nThe commercial pipeline: linking offers to their history\nAn offer does not appear from nowhere. It is the product of a chain of communications, decisions, and tasks — and that chain is what gives it context. When an agent retrieves an offer, it needs to understand not just its value and status, but the relationship history that generated it.\nThis is where the shared ID architecture pays off most clearly. Given an offer, the agent can filter for all emails, calls, and tasks linked to the same contact_id within the relevant date range — reconstructing the commercial conversation that led to the offer without any hardcoded joins. The pipeline becomes navigable by relationship, not just by record.\nThe offer\u0026rsquo;s own document carries its commercial summary: value, status, dates, and the contact it is directed at. The surrounding retrieval context — communications and tasks — provides the narrative. Together they give an agent everything it needs to reason about the commercial opportunity.\nTwo retrieval modes and the agent context assembly pattern\nEvery query in this architecture operates in one of two modes:\nGlobal semantic search — no metadata filter, maximum recall. Used when the agent doesn\u0026rsquo;t know where the answer lives: \u0026ldquo;find any contact who has raised pricing concerns in the last quarter.\u0026rdquo; The search spans all entity types and all companies.\nScoped retrieval — filtered by company_id, contact_id, or type. Used when the agent knows the subject and needs to assemble context: \u0026ldquo;give me everything relevant about Acme Corp.\u0026rdquo;\nThe scoped pattern is the foundation of agent context assembly. The sequence is:\n1. Retrieve the company rollup → orient the agent with a 360° summary 2. Filter by company_id + type:contact → get all active contacts 3. Filter by contact_id + type:[email,call,meeting] → get communication history 4. Filter by contact_id + type:task + status:open → get pending intentions 5. Filter by company_id + type:offer + status:active → get commercial state Each step is a fast metadata filter on the vector index, with semantic similarity used selectively where the content itself matters. The rollup document — generated periodically and always kept fresh — is the entry point that orients every subsequent step.\nThe cost of missing links\nRetrieval without relational context produces a specific failure mode: the right document surfaces, but the agent interprets it incorrectly because it lacks the surrounding context. An email about pricing retrieved in isolation looks like a negotiation. The same email, retrieved with the task that preceded it (\u0026ldquo;prepare revised offer — client is price-sensitive\u0026rdquo;) and the offer that followed it, is a milestone in a commercial story.\nMissing links don\u0026rsquo;t produce obvious errors. They produce plausible but incomplete answers — which in enterprise AI contexts can be more dangerous than obvious failures. The relational glue is not a nice-to-have. It is what separates a semantic search tool from a system that can actually reason about your business.\n7. Before You Embed: The Preprocessing Checklist #Architecture and granularity decisions mean nothing if the data going into the embedding model is dirty, inconsistent, or structurally broken. Preprocessing is the unglamorous work that determines whether everything else performs as designed. This section is a practical checklist — the things that must be right before any record touches an embedding model.\nDocument quality: nulls, templates, and free-text\nThe text field is the only thing the embedding model sees. Its quality is non-negotiable.\nStart with null handling. Every field that has no value must be omitted from the narrative entirely — not written as \u0026ldquo;phone: null\u0026rdquo; or \u0026ldquo;notes: none.\u0026rdquo; Null tokens dilute the semantic signal and push the vector toward meaningless regions of embedding space. If a contact has no recorded phone number, the contact document simply doesn\u0026rsquo;t mention a phone number.\nNext, build and maintain a narrative template for each entity type. The template defines what fields appear, in what order, and in what prose form. It should read as natural language — not a field dump. Templates should be versioned: when a template changes, all documents of that type need to be re-embedded.\nFinally, define a strategy for free-text fields. Notes and comments should be cleaned of obvious noise (duplicate whitespace, encoding artifacts, internal system tags) and appended to the narrative as a final sentence or short paragraph. They should never be the entire document — always anchored to the structured context around them.\nData hygiene: IDs and deduplication\nBefore ingestion, your entity IDs must be stable, unique, and consistent across all systems that will read or write them. An ID that changes between CRM exports, or that means different things in different contexts, will silently corrupt your relational glue.\nDeduplication is equally critical and frequently skipped. CRM systems accumulate duplicate contacts and companies over time — same person entered twice, same company under two slightly different names. Duplicates produce redundant vectors that dilute retrieval and confuse agents. Resolve duplicates in the source data before ingestion, not after.\nTemporal normalization\nCRM data is accumulated over years, across teams, sometimes across system migrations. Date formats are inconsistent. Timezones are missing or wrong. Relative references (\u0026ldquo;last Tuesday\u0026rdquo;) appear in free-text notes.\nNormalize all dates to ISO 8601 format with timezone before ingestion. Store them in metadata as structured fields — not embedded in the text where they become semantic noise. A date in metadata is filterable and sortable. A date in the text field is just a token the model will try to interpret semantically, usually poorly.\nFreshness: rollups and re-ingestion triggers\nA vector index that is not kept fresh becomes a liability. CRM data changes constantly — contacts update their roles, offers change status, tasks get closed. Stale vectors produce stale answers.\nDefine three re-ingestion triggers from the start:\nRecord update — any change to a source record in the CRM triggers re-embedding of the affected document Template change — a revision to any narrative template triggers re-embedding of all documents of that type Model change — replacing the embedding model requires full re-ingestion of the entire index Rollup documents have their own freshness cadence. Because they summarize across multiple entities, they cannot be triggered by a single record update. Generate them on a schedule — daily or weekly depending on data volatility — or on significant events such as a new offer being created or a contact changing role.\nEdge cases: multilingual data and long content\nEnterprise CRM data is rarely monolingual. Sales teams operate across countries, notes are written in the language of the conversation, email bodies mix languages within a single thread. Most embedding models handle multilingual input, but performance degrades when languages are mixed within a single document.\nWhere possible, detect the primary language of each document and keep it consistent. For mixed-language free-text fields, clean aggressively or truncate to the dominant language before embedding.\nLong content — particularly email bodies and meeting minutes — needs a length strategy. Most embedding models have a token limit. Content that exceeds it gets silently truncated, which can mean the most important part of a long email never makes it into the vector. Either summarize long content before embedding (using an LLM as a preprocessing step), or chunk it into overlapping segments with shared metadata, treating each chunk as its own document.\nSensitive data and PII\nBefore any record enters a shared vector index, consider what it contains. CRM data is dense with personally identifiable information — names, contact details, communication content, financial figures. Depending on your jurisdiction and use case, some of this data may be subject to regulatory constraints that affect where it can be stored and who can retrieve it.\nAt minimum: know what PII is in your index, ensure your vector database access controls are as strict as your relational database, and have a deletion strategy. When a contact is deleted from the CRM, their vectors must be deleted from the index — not left as orphaned embeddings that surface in retrieval.\nThe preprocessing checklist\nBefore any entity type goes into your embedding pipeline, verify:\nNull fields omitted from narrative text Narrative template defined, versioned, and reviewed for natural language quality Free-text fields cleaned and integrated into template Entity IDs stable, unique, and consistent across systems Duplicates resolved in source data All dates normalized to ISO 8601 with timezone Re-ingestion triggers defined for record updates, template changes, model changes Rollup generation schedule defined Language consistency checked per document Long content truncation or summarization strategy in place PII inventory completed and access controls verified Deletion propagation strategy confirmed 8. A New Profession Is Emerging #Everything described in this article — the entity mapping, the narrative templates, the granularity decisions, the metadata architecture, the freshness strategy — represents a coherent body of work. It is not software engineering. It is not data science. It is not CRM administration. It sits at the intersection of all three, and right now, almost nobody is trained to do it well.\nThat is about to change.\nA gap that is becoming impossible to ignore\nAs more enterprises move seriously into AI — deploying agents, building semantic search, automating workflows over their business data — the bottleneck is consistently the same: not the models, not the infrastructure, but the knowledge of how to prepare complex, heterogeneous business data for AI consumption.\nThe teams that crack this first are not the ones with the best embedding models or the most sophisticated vector databases. They are the ones with people who understand both sides of the problem — the business data structures that CRM systems encode, and the semantic architecture that AI systems require. That combination is rare, and its value is rising quickly.\nWhat this role looks like\nThe emerging professional in this space needs a specific blend of skills that no single traditional discipline covers:\nA deep familiarity with how business data is structured — not just technically, but semantically. Understanding why a contact-company relationship carries a time dimension, or why an overdue task is a relationship signal, is business domain knowledge, not just data modeling.\nFluency in semantic architecture — how embedding models work, what makes a good document, how vector databases organise and retrieve knowledge, how metadata enables filtering and relational traversal.\nAn engineering instinct for pipelines — ingestion cadences, re-embedding triggers, freshness strategies, deduplication, PII handling. The operational discipline to keep a live index reliable over time.\nAnd perhaps most importantly: the ability to translate between the business question and the data architecture. To look at a CRM schema and see not tables and fields, but a knowledge graph waiting to be unlocked.\nWhy the demand will grow\nEvery organisation that has accumulated years of CRM data is sitting on a knowledge asset that their AI systems cannot yet access — because nobody has built the bridge. As AI agents become standard infrastructure for sales, customer success, and business development teams, that bridge becomes critical path.\nThe organisations that invest in this capability now — building the ingestion architecture, training the people, establishing the practices — will compound that advantage over time. A well-structured semantic index of five years of customer relationships is not something a competitor can replicate quickly. It is institutional knowledge made machine-readable, and it is one of the most defensible assets an AI-enabled business can build.\nThe profession that builds and maintains these systems is emerging now, without a clear name yet, without established training paths, without job titles that have stabilised. That ambiguity is temporary. The need is not.\nIf you have read this article and found yourself thinking \u0026ldquo;someone needs to do this properly in my organisation\u0026rdquo; — that is the signal. The question is whether that someone will be you.\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_015/","section":"Articles del Blog Tecnològic","summary":"How to preprocess and architect heterogeneous business data for vector databases, semantic search, and AI agents — and why mastering this is becoming one of the most valuable skills in enterprise AI.","title":"Feeding the Machine Right: CRM Data Ingestion for AI Systems"},{"content":"Quan el projecte importa, les empreses trien nBCN Software. #Tres dècades d\u0026rsquo;experiència en enginyeria de programari, a la trobada de la tecnologia del demà.\nSom el soci tècnic de confiança per a desenvolupadors que exigeixen excel·lència i empreses que es neguen a comprometre\u0026rsquo;s. Des d\u0026rsquo;integracions complexes fins a aplicacions innovadores, tenim un historial comprovat en projectes d\u0026rsquo;arreu del món.\nJa sigui que necessiti modernitzar una plataforma heretada, integrar sistemes crítics o incorporar capacitats d\u0026rsquo;IA a producció, lliurem treball que resisteix la càrrega del món real. No prototips disfressats de productes, ni dreceres ocultes a l\u0026rsquo;arquitectura. Només enginyeria ben feta.\nDarreres Entrades del Blog: # Feeding the Machine Right: CRM Data Ingestion for AI Systems How to preprocess and architect heterogeneous business data for vector databases, semantic search, and AI agents — and why mastering this is becoming one of the most valuable skills in enterprise AI. FileMaker SVG Skill: Give Your AI Assistant FileMaker Icon Superpowers Transform your AI assistant into a FileMaker SVG expert with this comprehensive skill file. Generate, heal, and validate FileMaker-compatible icons using natural language commands in Claude, Cursor, Windsurf, and other AgentSkills-compatible AI tools. Lectura Recomanada # Vibe Code Your FileMaker Apps Democratizing FileMaker Development—Build Sophisticated Interfaces with Just a Description. Powered by FileMaker MCP Server + OData. Què Fem #Ens especialitzem en quatre dominis fonamentals de l\u0026rsquo;enginyeria de programari:\nArquitectura de Sistemes Complexos #Quan els seus requisits superen les solucions estàndard, dissenyem i construïm sistemes sofisticats des de zero. Acceptem la complexitat perquè els seus usuaris no l\u0026rsquo;hagin de gestionar, convertint la lògica de negoci intricada en aplicacions que se senten effortless d\u0026rsquo;operar.\nExplori el Nostre Treball →\nDesenvolupament FileMaker i Mòduls #Proporcionem mòduls provats en producció i llestos per al combat que estenen les capacitats de FileMaker amb funcionalitat avançada. Les nostres solucions eliminen la sobrecàrrega de desenvolupament mantenint la qualitat del codi i la consistència arquitectònica.\nExplori el Nostre Catàleg de Mòduls →\nIntegració de Sistemes i APIs #Connectem sistemes dispersos al seu stack tecnològic: plataformes de comerç electrònic, passarel·les de pagament, WordPress, Salesforce i aplicacions personalitzades. Les integracions complexes són la nostra especialitat.\nIntegració d\u0026rsquo;IA i Implementació de LLM #Integrem capacitats d\u0026rsquo;IA en aplicacions existents amb precisió. Des de sistemes de generació augmentada per recuperació (RAG) fins a implementacions locals de LLM, implementem IA en tots els nivells de complexitat mantenint la seguretat de dades i el rendiment del sistema.\nPer Què Triar nBCN? # Profunda Experiència — Més de 30 anys d\u0026rsquo;èxit comprovat arreu del món Entenent el Seu Negoci — Ens prenem el temps d\u0026rsquo;aprendre com treballa abans de programar Qualitat Primer — Cada solució construïda amb atenció al detall i millors pràctiques Associació a Llarg Termini — Estem invertits en el seu èxit més enllà de la finalització del projecte Escalable i Segur — Codi de grau de producció que aborda reptes empresarials reals Llest per Construir Algo Gran? #Expliqui\u0026rsquo;ns què està construint. Li direm com fer que duri.\nVeure el Nostre Portafoli → | Llegir el Nostre Blog → | Obtenir Recursos →\n","date":null,"permalink":"https://ntwk.es/ca/","section":"nBCN Software","summary":"","title":"nBCN Software"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/rag/","section":"Tags","summary":"","title":"RAG"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/","section":"Tags","summary":"","title":"Tags"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/vectordatabase/","section":"Tags","summary":"","title":"VectorDatabase"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/caldav/","section":"Tags","summary":"","title":"CalDAV"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/carddav/","section":"Tags","summary":"","title":"CardDAV"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/dav/","section":"Tags","summary":"","title":"DAV"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/integraci%C3%B3/","section":"Tags","summary":"","title":"Integració"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/m%C3%B2dul/","section":"Tags","summary":"","title":"Mòdul"},{"content":"Aplicacions Pre-empaquetades i Mòduls FileMaker #Els nostres mòduls estan evolucionant cap a un ecosistema natiu d\u0026rsquo;IA. Des del processament de documents i comunicacions fins a programació i informes, estem teixint grans models de llenguatge i agents intel·ligents en cada mòdul que lliurem, convertint utilitats independents en un conjunt d\u0026rsquo;eines coordinat i conscient d\u0026rsquo;IA.\nConstruïts amb les millors pràctiques de la indústria, documentació completa i integració perfecta en ment, cada mòdul proporciona funcionalitat específica per resoldre reptes empresarials comuns. Explori el catàleg a continuació per veure documentació, característiques i guies d\u0026rsquo;implementació.\n","date":null,"permalink":"https://ntwk.es/ca/modules/","section":"Mòduls","summary":"","title":"Mòduls"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/on-premise/","section":"Tags","summary":"","title":"On-Premise"},{"content":"Servidor DAV # Un servidor CalDAV i CardDAV autoallotjat i llest per a producció construït sobre Spring Boot, dissenyat per a organitzacions que necessiten sincronització confiable de calendaris i contactes sota la seva pròpia infraestructura — sense dependències de núvol, tarifes de subscripció, o dades sortint de les instal·lacions.\nLlançat — 1 de Març de 2026. S\u0026rsquo;emparella nativament amb el Mòdul FM GCalendar per permetre a la teva organització allotjar els seus propis serveis de calendari d\u0026rsquo;extrem a extrem, amb zero dependència de núvol externa. Què Proporciona # CalDAV — sincronització de calendaris i esdeveniments compatible amb RFC 4791 i RFC 5545 (iCalendar) CardDAV — sincronització de contactes i llibretes d\u0026rsquo;adreces compatible amb RFC 6352 i RFC 6350 (vCard) Tots dos serveis comparteixen una capa d\u0026rsquo;autenticació unificada, una única base de dades PostgreSQL, i un únic endpoint HTTPS — un servidor per desplegar i mantenir.\nCompliment de Protocol #El servidor implementa el conjunt complet de mètodes WebDAV requerits per clients CalDAV i CardDAV:\nMètode Propòsit OPTIONS Anunci de capacitats (DAV: 1, 2, calendar-access, addressbook) GET / PUT / DELETE CRUD d\u0026rsquo;esdeveniments i contactes PROPFIND Descobriment de propietats a profunditat 0, 1 i infinit REPORT Consultes de calendari i multiget (RFC 4791) MKCALENDAR Creació de col·lecció de calendari (RFC 4791 §5.3.1) Els endpoints d\u0026rsquo;auto-descobriment (/.well-known/caldav, /.well-known/carddav) i el descobriment de principals (/principals/{username}) estan implementats perquè els clients es puguin configurar amb només un nom d\u0026rsquo;amfitrió i credencials — sense entrada manual de ruta requerida.\nCompatibilitat de Clients #Provat i verificat amb:\nmacOS — Calendar.app i Contacts.app (auto-descobriment, sincronització completa, creació de calendaris) iOS / iPadOS — aplicacions natives de Calendari i Contactes Android — DAVx⁵ (client de sincronització compatible amb estàndards) Linux — Evolution, Thunderbird, GNOME Online Accounts, KDE Kontact Qualsevol altra aplicació compatible amb CalDAV / CardDAV La compatibilitat amb vCard es gestiona automàticament: el servidor emmagatzema vCards en el seu format original i converteix a vCard 3.0 en temps de servei per a clients — com macOS Contacts i Thunderbird — que no suporten vCard 4.0.\nCaracterístiques Principals #Sincronització\nDetecció de conflictes basada en ETag en cada creació i actualització Les actualitzacions de CTag (etiqueta de col·lecció) es propaguen immediatament a tots els clients REPORT Calendar-query amb filtrat per rang de temps per sincronització parcial eficient REPORT Calendar-multiget per recuperació massiva d\u0026rsquo;esdeveniments per UID Suport de grups de contactes amb format compatible amb Apple Seguretat\nHTTPS / TLS primer — corre al port 8443 amb suport SSL/TLS complet Autenticació HTTP Basic amb hash de contrasenya BCrypt (RFC 2617) Aïllament de dades per usuari via control d\u0026rsquo;accés basat en rutes (/caldav/{username}/, /carddav/{username}/) Operacions\nBackend PostgreSQL amb versionat d\u0026rsquo;esquema Flyway — els canvis d\u0026rsquo;esquema mai requereixen ALTER TABLE manual Perfils de Spring Boot per a entorns dev / prod API de gestió REST per a principals, calendaris, esdeveniments, llibretes d\u0026rsquo;adreces i contactes OpenAPI / Swagger UI inclòs per exploració d\u0026rsquo;API Endpoint de health check a /api/health per integració de monitoratge Optimització de consultes N+1 amb JOIN FETCH explícit — sense degradació de rendiment a escala Neteja automàtica de registre de canvis (retenció configurable, predeterminat 30 dies) Integració amb el Mòdul FM GCalendar #El Servidor DAV és el backend on-premise de contrapart del Mòdul FM GCalendar. Junts formen una infraestructura de calendari autoallotjada completa:\nEl Mòdul FM GCalendar gestiona esdeveniments dins de FileMaker, sincronitzant amb Google Calendar o directament amb el Servidor DAV. El Servidor DAV publica aquells calendaris i contactes als dispositius de cada usuari sobre CalDAV/CardDAV estàndard. Els canvis des de qualsevol dispositiu es sincronitzen de tornada a través del servidor — sense tercers al circuit. Aquesta combinació és l\u0026rsquo;única configuració que dóna a una organització centrada en FileMaker sincronització de calendari lectura/escriptura completa en tots els dispositius amb zero dependència de núvol externa.\nVisió General d\u0026rsquo;Arquitectura #Dispositius client (macOS / iOS / Android / Linux) │ HTTPS (port 8443) ▼ Servidor DAV (Spring Boot 3.2 · Java 17 · Jetty) │ ▼ PostgreSQL (principals · calendaris · esdeveniments · llibretes d\u0026#39;adreces · contactes) El servidor usa una cadena de filtres de servlet per interceptar mètodes WebDAV abans del despatxador de Spring, el que manté la capa de maneig de protocol clarament separada de l\u0026rsquo;API de gestió REST i de Spring Security.\nAPI de Gestió REST #Més enllà dels endpoints de protocol, una API REST completa està disponible per a operacions administratives:\nRecurs Endpoints Principals (usuaris) CRUD a /api/principals Calendaris CRUD a /api/calendars Esdeveniments CRUD a /api/calendar-objects Llibretes d\u0026rsquo;adreces CRUD a /api/addressbooks Contactes CRUD a /api/contacts Health GET /api/health Tots els endpoints estan documentats via OpenAPI 3.0 — accessibles a /swagger-ui.html i /rapidoc.html en una instància en execució.\nRequisits de Desplegament # SO Host: Linux (recomanat), macOS o Windows Runtime: Java 17 o posterior Base de dades: PostgreSQL 15+, accessible per xarxa Xarxa: Nom d\u0026rsquo;amfitrió aconseguible o endpoint VPN per connectivitat de client TLS: Certificat auto-signat inclòs per desenvolupament; porti el seu propi o usi Let\u0026rsquo;s Encrypt per a producció # Iniciar (perfil de desenvolupament, cert auto-signat) ./mvnw spring-boot:run # Iniciar (perfil de producció + TLS) ./mvnw -Pprod,tls spring-boot:run RFCs Implementades # RFC Estàndard RFC 4918 WebDAV — protocol principal RFC 4791 CalDAV — accés a calendaris RFC 5545 Format iCalendar RFC 6352 CardDAV — accés a contactes RFC 6350 Format vCard RFC 6764 Auto-descobriment (endpoints .well-known) RFC 2617 Autenticació HTTP Basic Preus # No hi ha botiga online. Aquest lloc no ven mòduls directament. Per a compres, pressupostos personalitzats, configuracions agrupades o sol·licituds especials, si us plau contacti\u0026rsquo;ns perquè puguem discutir termes, llicenciament i opcions d\u0026rsquo;implementació. Servidor DAV — Desplegament Base #Desplegament d\u0026rsquo;instància única en infraestructura del client. Inclou serveis CalDAV i CardDAV, configuració HTTPS, configuració d\u0026rsquo;esquema PostgreSQL, API de gestió REST, i aprovisionament inicial de principals i col·leccions.\nPreu Desplegament base 950 € Paquet d\u0026rsquo;Integració FM GCalendar #Configuració i verificació de la sincronització bidireccional entre el Mòdul FM GCalendar i el Servidor DAV. Inclou proves d\u0026rsquo;extrem a extrem amb almenys un client d\u0026rsquo;escriptori i un client mòbil.\nPreu Paquet d\u0026rsquo;integració 350 € Suport d\u0026rsquo;Implementació #Assistència in situ o remota per a configuració de servidor, configuració de xarxa, instal·lació de certificats, i onboarding de clients per a fins a cinc usuaris.\nPreu Suport d\u0026rsquo;implementació 500 € Suport de Manteniment #| Tarifa | Paquet | Mode | |:|:\u0026mdash;\u0026ndash;|:|:\u0026mdash;\u0026ndash;| | 80 €/hora | Paquet 5 hores | remot | | 60 €/hora | Paquet 30 hores | remot | | 120 € | una visita in situ | — |\nVisites in situ dins de l\u0026rsquo;àrea de Barcelona.\nActualitzacions #Les actualitzacions principals tenen un preu del 50% del cost de desplegament original.\nLes actualitzacions de manteniment són gratuïtes.\nGarantia #Garantia funcional permanent i il·limitada contra defectes al desplegament lliurat. La garantia roman activa indefinidament, excepte en cas de manipulació o una actualització al runtime Java subjacent, versió de PostgreSQL, o sistema operatiu que estigui fora de la matriu de compatibilitat acordada.\n","date":null,"permalink":"https://ntwk.es/ca/modules/dav_server/","section":"Mòduls","summary":"Servidor CalDAV i CardDAV autoallotjat i llest per a producció construït sobre Spring Boot. Sincronització confiable de calendaris i contactes a la teva pròpia infraestructura — compatible amb RFC, HTTPS-first, respatllat per PostgreSQL, provat amb clients macOS, iOS, Android i Linux. S\u0026rsquo;emparella nativament amb el Mòdul FM GCalendar per a una pila de calendari completament on-premise.","title":"Servidor DAV"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/webdav/","section":"Tags","summary":"","title":"WebDAV"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/agentskills/","section":"Tags","summary":"","title":"AgentSkills"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/automation/","section":"Tags","summary":"","title":"Automation"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/categories/development-tools/","section":"Categories","summary":"","title":"Development Tools"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/categories/filemaker/","section":"Categories","summary":"","title":"FileMaker"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/filemaker/","section":"Tags","summary":"","title":"FileMaker"},{"content":"FileMaker SVG Skill: Give Your AI Assistant FileMaker Icon Superpowers #Creating SVG icons that work perfectly in FileMaker Pro has always been a challenge. The FileMaker Pro 14 SVG Grammar specification is strict, and even small mistakes can break your button icons. But what if you could automate the entire process?\nWhat This \u0026ldquo;Skill\u0026rdquo; Actually Is #Let me be clear: this isn\u0026rsquo;t a traditional software application or plugin. The FileMaker SVG Icon Builder \u0026ldquo;skill\u0026rdquo; is a comprehensive SKILL.md file that instructs your AI assistant (like Claude, Cursor, Windsurf, or other AgentSkills-compatible agents) to handle everything about FileMaker SVG icons.\nWhen you install this skill, you\u0026rsquo;re essentially giving your AI assistant the complete knowledge base and tools to:\nGenerate FileMaker-compliant SVG code from natural language descriptions Automatically fix existing SVG files that don\u0026rsquo;t meet FileMaker\u0026rsquo;s requirements Validate SVG icons against the FileMaker Pro 14 specification Provide templates and examples for common icon patterns Think of it as a specialized expert that lives inside your AI coding assistant, ready to handle any FileMaker SVG task you throw at it.\nThe SVG Compatibility Problem #If you\u0026rsquo;ve ever tried to create custom SVG icons for FileMaker, you know the pain. Missing XML declarations, wrong namespaces, incompatible coordinate units—these issues can turn a simple icon creation task into hours of debugging.\nThe FileMaker SVG Icon Builder skill solves this problem by providing a complete toolkit for creating, healing, and validating SVG icons that work flawlessly with FileMaker Pro.\nWhat Makes This Skill Special #This isn\u0026rsquo;t just another SVG tool. It\u0026rsquo;s an AgentSkills.io compatible skill that integrates directly with AI agents like Claude Desktop, Windsurf IDE, Cursor, and others. The skill understands FileMaker\u0026rsquo;s specific requirements and handles all the technical details automatically.\nKey Capabilities #Create FileMaker-compliant SVG icons from scratch using natural language descriptions. Just tell the AI what you want, and it generates a properly formatted SVG.\nHeal existing SVGs to fix compatibility issues automatically. The included Python script can fix common problems like missing declarations, wrong namespaces, and coordinate unit issues.\nValidate against FileMaker Pro 14 SVG Grammar to ensure your icons will work perfectly before you even import them.\nTheme integration support with fm_fill for dynamic theming that adapts to your FileMaker solution\u0026rsquo;s color schemes.\nHow It Works in Practice #Installation Across Multiple Platforms #One of the best features is its broad compatibility. The skill works with:\nClaude Desktop - Install directly through the Skills panel Claude Code - Upload the skill file at claude.ai/code Windsurf IDE - Native skill integration Cursor - AI-first code editor support Cline - VS Code extension compatibility The AgentSkills.io standard means you can use the same skill across all these platforms without modification.\nNatural Language Icon Creation #Once installed, creating icons is as simple as:\n\u0026ldquo;Create a FileMaker SVG icon for a save button\u0026rdquo;\n\u0026ldquo;Build a theme-compatible FileMaker button bar icon for user management\u0026rdquo;\n\u0026ldquo;Generate a FileMaker-compatible trash icon with proper styling\u0026rdquo;\nThe AI understands FileMaker\u0026rsquo;s requirements and generates SVG code that just works.\nAutomated Healing and Validation #The real magic happens when you have existing SVGs that need fixing. The included Python scripts can:\n# Auto-fix compatibility issues python3 scripts/heal_filemaker_svg.py input.svg output.svg # Validate the result python3 scripts/validate_filemaker_svg.py your_icon.svg The healer automatically fixes:\nMissing XML declaration and namespaces Missing width/height attributes Unit symbols in coordinates (px, pt, cm, etc.) Negative radius values Degrees to radians conversion UTF-16 to UTF-8 encoding Complete Toolkit for Developers #The skill comes with everything you need:\nTemplate Assets - Pre-built SVG templates for common patterns like basic shapes, theme buttons, gradients, and reusable symbols.\nComprehensive Documentation - Complete FileMaker Pro 14 SVG Grammar specification with examples and best practices.\nPython Scripts - Automated healing and validation tools for batch processing existing icon libraries.\nReference Materials - Official Claris documentation links and detailed grammar specifications.\nReal-World Benefits #Time Savings #What used to take hours of manual debugging now takes minutes. The automated healing alone can save days of work when migrating existing icon libraries.\nConsistency #Every icon generated follows the same standards, ensuring your entire application has a consistent look and feel that works perfectly with FileMaker\u0026rsquo;s rendering engine.\nFuture-Proof #The AgentSkills.io standard means your investment in this skill pays off across multiple AI platforms and development environments.\nQuality Assurance #Built-in validation means you catch problems before they reach your users, preventing broken icons and inconsistent UI elements.\nGetting Started #The installation process is straightforward:\nDownload the skill file from GitHub Install it in your preferred AI agent Start creating icons with natural language commands For teams, the skill can be shared across multiple development environments, ensuring everyone follows the same standards.\nBeyond Basic Icons #While the skill excels at creating simple button icons, it also supports advanced features:\nGradient Support - Create icons with complex gradients that still comply with FileMaker\u0026rsquo;s requirements.\nSymbol Reuse - Build reusable symbol libraries for consistent icon sets across large applications.\nTheme Integration - Use fm_fill to create icons that automatically adapt to your FileMaker solution\u0026rsquo;s color themes.\nThe Bigger Picture #This skill represents a shift in how we approach FileMaker development. By combining AI agents with domain-specific knowledge, we can automate tedious technical tasks while maintaining the high quality standards that FileMaker developers expect.\nThe AgentSkills.io ecosystem is growing, and tools like this show how AI can enhance rather than replace developer expertise. You still control the design and user experience, but the technical implementation becomes effortless.\nConclusion #The FileMaker SVG Icon Builder skill transforms one of the most frustrating aspects of FileMaker development into a streamlined, automated process. Whether you\u0026rsquo;re creating a single icon or migrating an entire library, this tool ensures your SVG icons work perfectly every time.\nFor FileMaker developers who value both quality and efficiency, this skill isn\u0026rsquo;t just helpful—it\u0026rsquo;s essential.\nGet the skill: FileMaker SVG Icon Builder on GitHub\nLearn more: AgentSkills.io\nOfficial documentation: FileMaker Pro SVG Grammar\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_014/","section":"Articles del Blog Tecnològic","summary":"Transform your AI assistant into a FileMaker SVG expert with this comprehensive skill file. Generate, heal, and validate FileMaker-compatible icons using natural language commands in Claude, Cursor, Windsurf, and other AgentSkills-compatible AI tools.","title":"FileMaker SVG Skill: Give Your AI Assistant FileMaker Icon Superpowers"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/icons/","section":"Tags","summary":"","title":"Icons"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/svg/","section":"Tags","summary":"","title":"SVG"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/api/","section":"Tags","summary":"","title":"API"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/event-driven/","section":"Tags","summary":"","title":"Event-Driven"},{"content":"FileMaker Server Webhooks: The Integration Revolution That Changes Everything #How OData Webhooks Transform FileMaker from Database Platform to Event-Driven Integration Hub #Look, if you\u0026rsquo;ve been building FileMaker solutions for any length of time, you know the pain point I\u0026rsquo;m about to describe. It\u0026rsquo;s the one we\u0026rsquo;ve all learned to work around, the compromise we\u0026rsquo;ve all accepted as \u0026ldquo;just how things are.\u0026rdquo;\nI\u0026rsquo;m talking about real-time integration.\nFor decades, FileMaker has been amazing at what it does—rapid application development that actually works, custom solutions without the enterprise nightmares, getting stuff done fast. But getting FileMaker to play nicely with the rest of the modern software world? That\u0026rsquo;s always been\u0026hellip; let\u0026rsquo;s call it \u0026ldquo;friction.\u0026rdquo;\nWith FileMaker Server 22.0.4, something fundamental just changed.\nThe introduction of OData webhooks isn\u0026rsquo;t just another bullet point in the release notes. This is the kind of feature that makes you rethink what\u0026rsquo;s possible. It repositions FileMaker from being this isolated (albeit powerful) database platform into something that can genuinely hold its own in modern, event-driven architectures.\nAnd honestly? It\u0026rsquo;s about time.\nThe Polling Problem We\u0026rsquo;ve All Just Accepted #Here\u0026rsquo;s the thing. Until now, if you wanted external systems to stay in sync with your FileMaker data, you basically had two options. Both kinda sucked.\nOption 1: Polling. Your external system just keeps asking FileMaker, over and over, \u0026ldquo;Hey, anything changed? How about now? Now? What about now?\u0026rdquo; Every few seconds. Or minutes. Or whatever interval you decided was the least-bad compromise between being current and not hammering your server into the ground.\nIt wastes resources. It\u0026rsquo;s always a little bit behind. It scales terribly. And you end up writing all this complex state management code just to track what you\u0026rsquo;ve already processed. It works, sure. But it feels wrong the whole time you\u0026rsquo;re building it.\nOption 2: Manual triggers. You write FileMaker scripts that use Insert from URL to ping external systems when something happens. This works better, actually. Until it doesn\u0026rsquo;t. Because now your FileMaker business logic is all tangled up with integration concerns. And if that external API is down when your script fires? Well, you better have written some really solid error handling. Which you probably didn\u0026rsquo;t, because you were trying to ship a feature, not build NASA-grade fault tolerance.\nBoth approaches share the same fundamental problem: FileMaker has been reactive, not proactive. It responds to queries. It doesn\u0026rsquo;t initiate conversations.\nWebhooks flip this entire model on its head.\nEvent-Driven FileMaker: Wait, This Actually Works Now? #With OData webhooks, FileMaker Server actively monitors your data and tells external systems the instant something relevant happens. No polling. No scripts with Insert from URL praying the network gods smile upon them.\nThis is event-driven architecture. The same pattern Stripe uses. And Shopify. And GitHub. And basically every modern SaaS platform you can name.\nBut here\u0026rsquo;s what makes FileMaker\u0026rsquo;s implementation actually good:\nIt\u0026rsquo;s standards-based. They built this on OData v4. Which means it speaks a language that thousands of platforms already understand. This isn\u0026rsquo;t some proprietary Claris thing that only works with Claris tools. It\u0026rsquo;s a widely adopted standard with real tooling and actual documentation that exists outside the Claris ecosystem.\nYou get granular control. You define exactly what triggers notifications using OData filter expressions. You specify which fields get included in the payload with the \u0026ldquo;select\u0026rdquo; parameter. You control where notifications go. This precision means you\u0026rsquo;re not just blasting entire records around your infrastructure every time someone breathes near a field. You\u0026rsquo;re surgical about it.\nWebhooks are first-class API resources. Create them. Retrieve them. List them. Delete them. Manually invoke them for testing. All through standard OData endpoints. Which means you can version-control these things, automate them, manage them programmatically. They\u0026rsquo;re not buried in some admin console checkbox—they\u0026rsquo;re infrastructure as code.\nTesting is built in. You can manually fire a webhook with specific record IDs. So you can test your integrations without modifying production data or sitting around waiting for real-world events to happen. As someone who\u0026rsquo;s spent too many hours waiting for the right conditions to test an integration, this is huge.\nThis isn\u0026rsquo;t some bolt-on feature they rushed out. It\u0026rsquo;s a thoughtfully designed integration framework that actually respects how we work in 2025.\nWhat This Does for FileMaker\u0026rsquo;s Reputation #Let me be blunt here. FileMaker has an image problem.\nWe know the platform is powerful. We know it\u0026rsquo;s productive. We\u0026rsquo;ve built incredible things with it. But out there in the wider tech world? People still think of it as a \u0026ldquo;legacy platform.\u0026rdquo; Or they dismiss it as something that can\u0026rsquo;t handle modern architectures.\nWebhooks change that story. Completely.\nSuddenly FileMaker does the same integration patterns as cutting-edge SaaS platforms. When some startup architect is designing their tech stack and wondering if FileMaker fits, webhooks eliminate a major objection. When an enterprise is evaluating whether their FileMaker solutions can coexist with microservices, the answer becomes an unqualified yes.\nBut here\u0026rsquo;s the really exciting part: this opens up the entire iPaaS ecosystem. Zapier, Make (used to be Integromat), n8n, Workato, all those integration platforms with thousands of pre-built connectors.\nA FileMaker solution with webhooks can now trigger a Zapier workflow that updates Salesforce, sends a Slack notification, creates a QuickBooks invoice, and logs everything to Datadog. Without writing a single line of custom integration code. You just configure it.\nThat\u0026rsquo;s a force multiplier.\nReal Use Cases: What Becomes Possible Now #Okay, enough abstract talk. Let me show you three scenarios that were either impossible or ridiculously painful before, and are now actually straightforward.\nReal-Time Financial Reconciliation #Picture a manufacturing company. They\u0026rsquo;re using FileMaker for production management—work orders, materials, labor tracking, the whole operation. But their accounting lives in QuickBooks Online, because of course it does.\nBefore webhooks, syncing these systems meant either scheduled batch jobs (with all the delays that entails) or building custom middleware that someone has to maintain forever.\nNow? The moment a production order status changes to \u0026ldquo;Completed\u0026rdquo; in FileMaker, a webhook fires. It contains the order details, materials used, labor hours, client info. That hits a lightweight serverless function—could be AWS Lambda, could be Cloudflare Workers, doesn\u0026rsquo;t matter—that calculates the final cost, hits the QuickBooks API to create an invoice, then calls back to FileMaker\u0026rsquo;s Script API to mark the order as \u0026ldquo;Invoiced\u0026rdquo; and store the QuickBooks invoice ID.\nThe whole thing happens in seconds. Not minutes. Not \u0026ldquo;overnight batch.\u0026rdquo; Seconds.\nYour financial records stay reconciled in real-time. Discrepancies get caught immediately, not during month-end closing when you\u0026rsquo;re already stressed. Faster cash flow. Less accounting overhead. No more reconciliation errors from batch sync timing issues.\nIt just works.\nSupply Chain Event Streams #Here\u0026rsquo;s a logistics company managing their fleet, shipments, warehouse operations—all in FileMaker. Their customers want real-time visibility into shipment status. Their warehouse systems need to coordinate receiving. Their financial systems need to recognize revenue on delivery confirmation.\nThey set up webhooks on the Shipments table with filters for status changes. Now they\u0026rsquo;ve got an event stream architecture that looks a lot like what Amazon or FedEx runs internally. Except it\u0026rsquo;s built on FileMaker.\nShipment goes \u0026ldquo;Out for Delivery\u0026rdquo;? Webhook fires. That event fans out to multiple subscribers: customer portal shows live tracking, customer\u0026rsquo;s system gets an API callback with the delivery window, the internal routing system recalculates the remaining deliveries for optimization.\nStatus changes to \u0026ldquo;Delivered\u0026rdquo;? Another cascade. Delivery confirmation email with photo and signature. Customer\u0026rsquo;s accounts payable system gets notified. FileMaker Script creates the invoice and calculates driver performance metrics. Event gets logged to the data warehouse for BI.\nAnd here\u0026rsquo;s where it gets really good: exception handling. They\u0026rsquo;ve got a webhook with a filter—DeliveryStatus eq \u0026lsquo;Exception\u0026rsquo;. The instant something goes wrong, the operations team gets alerted via PagerDuty, a high-priority ticket gets created in Zendesk, and the customer gets proactive communication about what\u0026rsquo;s being done to fix it.\nAll automatic.\nThis transforms FileMaker from \u0026ldquo;the database\u0026rdquo; into an event source driving a sophisticated distributed system. That\u0026rsquo;s not something you could say about FileMaker a year ago.\nCompliance and Anomaly Detection in Pharma #Pharmaceutical company. Sample management and clinical trial coordination in FileMaker. Heavily regulated environment—every data change needs to be audited, anomalies need to be detected in real-time.\nThey set up webhooks monitoring their SampleInventory and TrialData tables. Schema change notifications are enabled. Now every record change triggers a webhook that sends complete before/after field values to an append-only log—AWS S3 with cryptographic signatures. That\u0026rsquo;s your tamper-proof audit trail right there. FDA 21 CFR Part 11 compliant.\nBut it gets better. Those webhook payloads flow into a machine learning pipeline. Could be AWS Lambda calling SageMaker. Could be Azure Functions. Doesn\u0026rsquo;t matter. Point is, it\u0026rsquo;s watching for anomalies in real-time.\nUnusual access patterns. Changes happening during non-business hours. Rapid successive modifications that might indicate data manipulation. Schema changes that could affect data integrity. The ML catches these patterns and immediately creates incident tickets, notifies the QA team with full context, triggers FileMaker Script callbacks to flag affected records for review, and generates preliminary incident reports.\nAnd because they enabled notifySchemaChanges, any modification to table structure or field definitions triggers instant alerts. So nobody accidentally changes something that could invalidate months of clinical data.\nA year ago, getting this level of audit capability meant buying expensive third-party add-ons or commissioning custom plugin development. Now? Standard cloud services and a few hundred lines of serverless code.\nDifferent ballgame entirely.\nThe Ripple Effects Nobody\u0026rsquo;s Talking About Yet #The direct technical capabilities are obvious. But there are second-order effects that are going to be just as important.\nDeveloper skills are going to level up. FileMaker developers now have actual reasons to learn event-driven architecture, serverless computing, modern API patterns. That makes us more valuable. It broadens what we can build. And honestly, it\u0026rsquo;s more interesting work.\nThe partner ecosystem is about to expand. Third-party vendors will build webhook-based integration frameworks. Pre-built connectors. Specialized services. That ecosystem growth benefits all of us through shared knowledge and reusable components. We won\u0026rsquo;t all be reinventing the same wheels.\nWe\u0026rsquo;re going to develop patterns. The FileMaker community is going to figure out best practices for webhook design. How to structure payloads. When to use filters versus script-side logic. Patterns for error handling and retry logic. Security approaches. These patterns will become part of our collective knowledge, the same way we\u0026rsquo;ve developed patterns for everything else in FileMaker over the years.\nPlatform credibility just went up. When FileMaker comes up in technical discussions about platform choices, webhooks give us a real argument. \u0026ldquo;Does it support webhooks?\u0026rdquo; is a standard question in due diligence now. FileMaker can answer yes without asterisks or qualifications.\nThat matters more than you might think.\nWhat\u0026rsquo;s Next for This Feature #Look, webhook support is probably just the beginning. FileMaker\u0026rsquo;s clearly committed to evolving toward modern integration patterns.\nWe might see webhook response handling for synchronous request/response patterns. Event sourcing capabilities. GraphQL subscriptions. Maybe a webhook marketplace where developers share pre-configured integrations. Native serverless platform integration that makes deploying webhook receivers as easy as writing a FileMaker script.\nThe foundation\u0026rsquo;s in place now. Where it goes from here depends partly on what we build with it.\nThe Bottom Line #Adding OData webhooks to FileMaker Server isn\u0026rsquo;t just a feature update. It\u0026rsquo;s a statement about where the platform is going and what it means to build on FileMaker in 2025 and beyond.\nIf you\u0026rsquo;ve chosen FileMaker because it lets you ship solutions fast, webhooks eliminate a major compromise you\u0026rsquo;ve been making. You don\u0026rsquo;t have to sacrifice modern integration patterns to get rapid development anymore. You can have both.\nIf your business has invested in FileMaker solutions, webhooks give you a path into digital transformation initiatives without ripping out and replacing systems that work. Your FileMaker solutions can integrate seamlessly with best-of-breed tools across your organization.\nAnd for the platform itself, webhooks represent a commitment to evolution. To meeting developers where modern architecture is going, not where it used to be.\nThe question for FileMaker developers isn\u0026rsquo;t \u0026ldquo;Can FileMaker integrate with modern systems?\u0026rdquo; anymore.\nIt\u0026rsquo;s \u0026ldquo;What are you going to build now that it can?\u0026rdquo;\nBecause honestly? The possibilities are kind of spectacular.\nFurther Reading:\nClaris FileMaker OData API Guide: https://help.claris.com/en/odata-guide/ OData v4 Specification: https://www.odata.org/ Event-Driven Architecture Patterns: Martin Fowler\u0026rsquo;s Enterprise Integration Patterns ","date":null,"permalink":"https://ntwk.es/ca/posts/post_013/","section":"Articles del Blog Tecnològic","summary":"How OData Webhooks transform FileMaker from database platform to event-driven integration hub, enabling real-time integrations that were previously impossible or painful to implement.","title":"FileMaker Server Webhooks: The Integration Revolution That Changes Everything"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/categories/integration/","section":"Categories","summary":"","title":"Integration"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/integration/","section":"Tags","summary":"","title":"Integration"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/odata/","section":"Tags","summary":"","title":"OData"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/webhooks/","section":"Tags","summary":"","title":"Webhooks"},{"content":"Mòdul Sistema de Formularis # Una solució FileMaker completa, llista per desplegar, per crear i gestionar formularis web dinàmics il·limitats.\nCaracterístiques Incloses # Formularis il·limitats i camps il·limitats per formulari Suport complet de tipus de camp: Text, Àrea de Text, Grup de Caselles, Botons de Ràdio, Desplegable, Selector de Data/Hora, Càrrega d\u0026rsquo;Arxiu, etc. Opcions avançades de camp: flag requerit, placeholder, opcions multi-valor (separades per pipe), regles de validació Sistema de subscripció d\u0026rsquo;usuaris amb enllaços segurs únics i protecció opcional per contrasenya Emmagatzematge d\u0026rsquo;enviaments amb pre-ompliment opcional de dades anteriors (perfecte per validació, confirmació o formularis multi-pas) Bloqueig opcional d\u0026rsquo;enviament únic després d\u0026rsquo;enviament final Marca corporativa completa: càrrega de logo (via carregador integrat basat en contenidors), nom d\u0026rsquo;empresa, lloc web, dades de contacte, peu legal Vista prèvia de formulari integrada directament a FileMaker Registre complet d\u0026rsquo;activitat Frontend web i formularis multilingües (crear un formulari per idioma; backend disponible en Català, Espanyol, Anglès – idioms il·limitats possibles) Gestió de fitxers adjunts amb tamany màxim configurable i tipus permesos Suport de tema Fosc / Clar al frontend web Estructura llista per integració (base de dades/taula objectiu, contenidors d\u0026rsquo;adjunts, hooks d\u0026rsquo;API personalitzats) Requisits Tècnics # FileMaker Pro 19+ o FileMaker Go (client) FileMaker Server 19+ amb Data API habilitat Plugin BaseElements v4.2 o superior Servidor web públicament accessible amb PHP 8.0+ (Apache o Nginx) Certificat SSL vàlid (Let\u0026rsquo;s Encrypt disponible per versions FileMaker Server \u0026gt; 21) No hi ha botiga online. Aquest lloc no ven mòduls directament. Per a compres, pressupostos personalitzats, configuracions agrupades o sol·licituds especials, si us plau contacti\u0026rsquo;ns perquè puguem discutir termes, llicenciament i opcions d\u0026rsquo;implementació. Versió Bàsica #245 € (llicència única)\nQuè NO està Inclòs a la Versió Bàsica # Disseny personalitzat UI/UX o estils CSS dels formularis web Manuals detallats d\u0026rsquo;usuari o administrador Formació d\u0026rsquo;usuaris finals Compra/instal·lació de certificat SSL Serveis Opcionals # Servei Preu Notes Implementació i desplegament complet (FileMaker Server + servidor web PHP + configuració SSL) 350 € Única vegada, remot o in situ Estils personalitzats / modificacions UI Pressupost separat Per projecte Sessions de formació (admin i usuaris) 80 €/hora Remot Manteniment i suport – remot 80 €/hora o 60 €/hora (pack 5h) Facturació en increments de 60 min Visita in situ (àrea metropolitana Barcelona) 120 € + tarifes regulars de Manteniment i suport Llicenciament per Volum per a Desenvolupadors i Proveïdors de Solucions #Plans de desenvolupador disponibles, si us plau contacti per condicions i polítiques de llicenciament.\nActualitzacions i Actualitzacions # Actualitzacions de versió principal (noves característiques, canvis arquitectònics): 50% del preu de llista actual Actualitzacions de manteniment i correcció d\u0026rsquo;errors: Sempre gratuïtes Garantia #Garantia de per vida contra defectes al mòdul lliurat, sempre que no s\u0026rsquo;hagin realitzat modificacions no autoritzades i la solució s\u0026rsquo;executi en versions de FileMaker suportades en ús en el moment de l\u0026rsquo;entrega.\nTermes de Llicència (Client Final) #Llicència no exclusiva, no transferible i perpetua per a ús intern únicament. La enginyeria inversa, redistribució o modificació del codi font està estrictament prohibida.\nTermes de Llicència (Desenvolupadors) #Autoritzat per integrar el mòdul en solucions de clients sota el programa de descompte per volum anterior. No s\u0026rsquo;otorguen drets de redistribució més enllà de les implementacions específiques cobertes per llicències comprades.\nEstarem encantats de proporcionar una demostració o instal·lació pilot completament funcional perquè pugui provar el mòdul en el seu entorn abans de la compra.\nPer preguntes o pressupostos personalitzats, contacti\u0026rsquo;ns a: tecnic@ntwk.es | +34 669 85 58 72\nVàlid fins al 31 de Desembre de 2026\nCaptures de Pantalla # Secció de captures de pantalla: Les captures de pantalla detallades de la interfície FileMaker, configuració del backend i vistes del frontend web estan disponibles a la versió en anglès. Tota la funcionalitat mostrada està completament disponible en aquesta versió del mòdul. ","date":null,"permalink":"https://ntwk.es/ca/modules/forms_system_module/","section":"Mòduls","summary":"","title":"Mòdul Sistema de Formularis"},{"content":"Vibe Code Your FileMaker Apps #Democratizing FileMaker Development—Build Sophisticated Interfaces with Just a Description #Powered by FileMaker MCP Server + OData # Building on the Foundation #In my last article, I introduced the FileMaker OData MCP Server—a game-changing bridge between Claris FileMaker and AI assistants. Today, I want to show you what becomes possible when you actually use it.\nThis article demonstrates real, practical vibe coding: how you move from describing an idea to deploying a working application, all without touching a line of code.\nWhat This Changes #The FileMaker MCP Server exposes a full OData v4 endpoint, enabling AI assistants to discover your Claris FileMaker database schema and access live data using only natural language. No complex API knowledge required. No custom development. Just describe what you want to build, and the AI handles the rest.\nStep 1 – Switch to Production Database #The journey starts simple. Set up as many database connections as you need—production, staging, development, client databases—then just ask the AI to switch to whichever one you want to work with. No credentials to manage in the conversation. Just point and go.\n*Click image to zoom/enlarge*\nResult: Production connection confirmed — real data is now accessible. Your assistant now has live, direct access to your actual business data. Step 2 – Retrieve Live Contact Records #Ask for what you need in plain English: \u0026ldquo;Show me the first five contacts\u0026rdquo; or \u0026ldquo;Get me all recent leads.\u0026rdquo; The assistant queries your live Claris FileMaker database and returns real records instantly.\n*Click image to zoom/enlarge*\nResult: Live data retrieved directly from the FileMaker server. In this example, we get our first five real contacts, including Elizabeth Thompson (ID 1002), pulled directly from production. Step 3 – Full Schema Introspection Without Documentation #This is where the magic happens. The assistant automatically discovers your entire database structure—every table, every field, every relationship—by reading the OData metadata. Zero documentation needed. Zero guesswork.\nThe AI understands how your contacts relate to opportunities, invoices to line items, orders to shipments. It sees the relationships you defined in FileMaker and immediately grasps how your data is connected.\n*Click image to zoom/enlarge*\nResult: Complete reverse-engineering of your database structure using only standard OData metadata. The assistant now knows your data model as well as you do—without you having to explain a thing. This is pure schema discovery at work. Real-World Use Case: Vibe Code Your First Utility #Now that the assistant understands your database, you can describe what you want to build—naturally, without technical jargon.\n\u0026ldquo;Draft a professional meeting request email to the contact I just looked up.\u0026rdquo;\nThe assistant uses the live contact data (Elizabeth Thompson) and creates a ready-to-use email. No context switching. No manual lookups. Real data, instantly at your fingertips.\nThis demonstrates the power of \u0026ldquo;vibe coding\u0026rdquo;—describing your intent in natural language, and having a working solution appear.\n*Click image to zoom/enlarge*\nResult: A professional, personalized email drafted using real data from your database. This is how you collaborate with AI: you describe the outcome, it handles the technical details. Build Your First Web Interface #Want a customer dashboard? A lead pipeline tracker? An invoice approval UI? Just describe it.\n\u0026ldquo;Build me a simple dashboard showing my top contacts and their recent orders.\u0026rdquo;\nThe assistant instantly generates a complete, interactive web application—HTML, CSS, JavaScript—all working with your live FileMaker data. No coding knowledge required. No framework setup. No build tools.\n*Click image to zoom/enlarge*\nResult: A fully functional web interface, ready to use. You can paste it into a FileMaker Web Viewer, share it as a standalone URL, or embed it anywhere. It connects directly to your FileMaker data through the OData endpoint. Scale to Complex, Multi-Table UIs #As you get comfortable, you can ask for increasingly sophisticated interfaces. Want a contact management system with related opportunities, activities, and notes all displayed together? Just ask.\n\u0026ldquo;Build a contact detail view that shows all their opportunities on one side, recent activities in the middle, and communication history on the right. Make it look professional.\u0026rdquo;\nThe assistant leverages its complete understanding of your database structure and creates rich, multi-table interfaces that would normally require days of development work. Filtering, sorting, related data lookups—all handled seamlessly.\n*Click image to zoom/enlarge*\nResult: A sophisticated, multi-table user interface built entirely through natural language requests. No HTML. No JavaScript. No API coding. You described what you wanted; the AI built it. How \u0026ldquo;Vibe Coding\u0026rdquo; Differs from Traditional Development #Traditional approach: Write a requirements document → brief a developer → wait for mockups → iterate through revisions → deploy → maintain the code.\nVibe coding approach: Describe what you want → get a working interface instantly → tweak it with feedback → deploy → iterate in seconds.\nThere\u0026rsquo;s no gap between your idea and a working prototype. You\u0026rsquo;re not managing developers or learning code syntax. You\u0026rsquo;re having a conversation with an AI that understands your database and builds what you describe.\nReal Deployment Options #Your newly built interfaces aren\u0026rsquo;t locked into Claude or any temporary workspace. You have immediate options:\nFileMaker Web Viewer: Copy the generated HTML/CSS/JavaScript directly into a Web Viewer. Your interface appears inside your FileMaker solution, connected to live data.\nStandalone Web Client: Share the interface as a public or private URL. Users access it from any browser—no FileMaker client needed. Perfect for customer portals, partner dashboards, or internal tools.\nEmbed Anywhere: The AI generates standard web code that works anywhere—your website, an intranet, a mobile app webview, or an internal portal.\nWhy This Matters for FileMaker Users #Speed: What would take days of development now takes minutes.\nNo Code Barrier: You don\u0026rsquo;t need to learn JavaScript, React, or any framework. You describe; the AI builds.\nLive Data, Instantly: Your interfaces connect directly to your FileMaker database. No manual syncing. No data exports. Always current.\nFlexibility: Tired of your dashboard? Describe a different one. Want to A/B test two designs? Generate both in seconds.\nRapid Iteration: Get feedback from users and incorporate changes immediately, in real time, without a development cycle.\nFrom Idea to Production #The entire workflow is streamlined:\nDescribe what you want to build in plain English Generate a fully functional web interface in seconds Customize it with feedback through natural conversation Deploy directly into a Web Viewer or as a standalone app Iterate and improve without waiting for developers All while your interface works with real, live data from your FileMaker database.\nConclusion: Democratizing FileMaker Development #The FileMaker MCP Server transforms any solution into a fully discoverable, queryable API. Combined with AI-powered vibe coding, it democratizes FileMaker development. You no longer need specialized knowledge to build sophisticated interfaces. You don\u0026rsquo;t need to hire developers for every new dashboard or utility. You don\u0026rsquo;t need to maintain complex code.\nInstead, you describe what you need, and it exists. Your data is live. Your interfaces are functional. Your business moves faster.\nThis is the future of low-code development: not \u0026ldquo;less code,\u0026rdquo; but no code—just conversation, and immediately useful tools.\nReady to build? Describe what your users need, and let AI handle the rest.\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_012/","section":"Articles del Blog Tecnològic","summary":"","title":"Vibe Code Your FileMaker Apps"},{"content":"In my previous post, I introduced the FileMaker Data API MCP Server—a bridge that gave AI agents deep introspection into your FileMaker schema, logic, and workflows.\nThat was about intelligence: letting AI see how your system thinks.\nThis next step is about interoperability—letting it talk to the world.\nIntroducing: FileMaker OData MCP Server # Now live → filemaker-odata-mcp\nWhy OData Changes Everything #FileMaker\u0026rsquo;s native OData support is powerful—but underused.\nThis MCP server turns it into a universal data passport.\nAny OData-compliant client—AI agent, Power BI, web app, or integration—can now query, filter, join, and explore your FileMaker data using standard REST syntax.\nNo custom APIs. No middleware. Just clean, discoverable data.\nAI Agents That Speak OData (and FileMaker) #With FileMaker OData MCP, any Model Context Protocol (MCP)–compatible agent can:\nRun live OData queries with $filter, $select, $expand, and pagination Merge FileMaker data with SAP, Dynamics, Salesforce, or custom APIs Map semantics across systems for cross-domain reasoning Generate real-time insights across your entire data universe FileMaker is no longer an island—it\u0026rsquo;s a node in the global data fabric.\nReal-World Impact #Picture this:\nAn AI agent syncing FileMaker orders with ERP in real time A CFO pulling live FileMaker KPIs into Excel or Power BI via OData A developer feeding FileMaker records into a generative AI workflow—no ETL required FileMaker becomes part of the conversation, not behind it.\nBuilt for Developers, Secured for Enterprises # Node.js + NPM — npm install filemaker-odata-mcp Maps directly to FileMaker Server\u0026rsquo;s OData endpoints Full auth \u0026amp; access control (Basic, OAuth, FM tokens) Dynamic schema exposure for AI discovery Runs standalone or alongside Data API MCP for dual introspection + connectivity Quick note on the roadmap: To ensure broad compatibility with older FileMaker Server versions, we\u0026rsquo;ve intentionally omitted some exciting new OData features introduced in FileMaker v22 (like enhanced metadata querying and advanced relational expansions). These are high on our TODO list for future releases—check out the detailed roadmap for what\u0026rsquo;s coming next. Your feedback here could shape it!\nThe Vision: AI That Understands and Connects # MCP Server Superpower Data API MCP AI understands your FileMaker logic OData MCP AI connects it to the world Together, they enable AI-native FileMaker ecosystems—open, intelligent, and interoperable by design.\nGet Started Today #👉 NPM: npm install filemaker-odata-mcp 👉 GitHub: FMS-ODATA-MCP 👉 Docs in repo — 5-minute setup guide included\nWhat happens when your FileMaker data speaks the same language as AI, BI, and the cloud?\nWhat new workflows will emerge when your system isn\u0026rsquo;t just smart—but connected?\nLet me know in the comments—I\u0026rsquo;d love to hear your ideas.\nBig thanks to the incredible @Claris International team for building such a flexible platform, and shoutout to @FileMaker devs worldwide pushing the limits of low-code + AI.\nLet\u0026rsquo;s keep building the future of connected intelligence together!\n#FileMaker #OData #AI #MCP #LowCode #DataIntegration #OpenSource\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_011/","section":"Articles del Blog Tecnològic","summary":"","title":"The Next Leap: Open Data Connectivity for AI-Powered FileMaker Solutions"},{"content":"AI Agents That Understand Your Entire FileMaker Solution #For decades, we\u0026rsquo;ve built complex FileMaker applications through expertise and countless iterations. Expert developers spend years mastering the nuances—table relationships, orchestrating scripts, business logic embedded throughout.\nWhat if you could hand that entire knowledge base to an AI agent?\nIntroducing the FileMaker Data API MCP Server—giving AI agents the ability to completely introspect your FileMaker solution and become an architect-level coder capable of building complex applications from simple human requests.\nThe Breakthrough #Imagine: \u0026ldquo;Build me a project management system that tracks tasks across teams, with automatic escalation when deadlines are missed and a dashboard showing capacity by department.\u0026rdquo;\nAn AI agent with full visibility into your FileMaker solution can:\nUnderstand your entire data architecture — tables, fields, relationships, constraints Learn your design patterns — existing scripts, layouts, workflows Comprehend your business logic — how your organization solves problems Generate production-ready code — that fits your ecosystem This is an AI architect that studied your codebase and can design applications native to your infrastructure.\nHow It Changes Development #Scalable Innovation — Stop waiting for senior developers. Get sophisticated applications architected instantly.\nPreserve Knowledge — Your FileMaker solutions contain years of wisdom. An AI agent becomes a knowledge multiplier.\nConcept to Code in Minutes — Move from conversation to working applications faster than ever.\nMaintain Consistency — Generated code follows your standards and patterns.\nPowered by Complete Introspection # Full database introspection — layouts, scripts, tables, relationships Script analysis and logic understanding Live execution capability — to test generated code Multi-database awareness Complete context — portals, global fields, containers All secure. No exposed credentials.\nThe Vision #We\u0026rsquo;re at an inflection point. AI isn\u0026rsquo;t automating routine tasks—it\u0026rsquo;s becoming a partner in creative, architectural work. For FileMaker developers, this means unlocking the next level: describing complex requirements in natural language and getting back production-grade, architecturally-sound applications.\nThis only works when AI has complete visibility into your solution. When it understands your data schema and your design philosophy. When it sees patterns and extends them intelligently.\nThat\u0026rsquo;s the real superpower.\nReady to Start? #The FileMaker MCP Server is open-source and ready.\n🔗 GitHub Repository\nWhat would you build if you had an AI architect with complete understanding of your FileMaker systems?\n#FileMaker #AI #Automation #SoftwareDevelopment #AIAgents #LowCode\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_002/","section":"Articles del Blog Tecnològic","summary":"","title":"The Real Superpower of AI"},{"content":"Building a Logstash/Elasticsearch/Kibana Dashboard #Transform your FileMaker data into actionable intelligence with real-time monitoring and visualization. Learn how to automatically feed FileMaker data into the Logstash/Elasticsearch/Kibana (ELK) stack using FileMaker\u0026rsquo;s JDBC interface. This comprehensive guide walks you through setting up seamless data ingestion, creating powerful dashboards, and gaining instant visibility into your critical business metrics—all without custom development complexity.\nThe Challenge: FileMaker Data Visibility #FileMaker has long been a reliable workhorse for organizations managing critical business data. Yet many teams face a common frustration: getting real-time visibility into that data across their organization. Traditional FileMaker reporting is powerful but static, often requiring manual exports, scheduled scripts, or complex web publishing solutions to share insights beyond the immediate user base.\nWhen you need to monitor performance metrics, track system health, meter usage patterns, and log activities in near real-time, FileMaker alone isn\u0026rsquo;t designed for this level of operational intelligence. That\u0026rsquo;s where the ELK stack comes in.\nWhy ELK? The Power of Elasticsearch, Logstash, and Kibana #The Elasticsearch-Logstash-Kibana (ELK) stack has become the industry standard for real-time data analytics and monitoring. Here\u0026rsquo;s why it\u0026rsquo;s the perfect complement to FileMaker:\nElasticsearch provides lightning-fast full-text search and analytics capabilities, handling millions of records with sub-second query response times. Logstash acts as your data processing pipeline, transforming and enriching raw data before it enters Elasticsearch. Kibana delivers intuitive, interactive dashboards that bring your data to life with visualizations, alerts, and deep-dive analytics.\nTogether, they create a scalable, open-source platform designed for real-time insights—something FileMaker wasn\u0026rsquo;t architected to do at scale.\nConnecting FileMaker to the ELK Stack via JDBC #FileMaker\u0026rsquo;s JDBC interface is the bridge between your FileMaker database and the broader data ecosystem. JDBC (Java Database Connectivity) allows external applications to query FileMaker as if it were a standard SQL database, making it possible to treat FileMaker as a data source for pipeline tools like Logstash.\nWhat You\u0026rsquo;ll Need #Before diving into setup, ensure you have:\nFileMaker Server 17 or later (with JDBC driver enabled) FileMaker JDBC driver installed and configured Logstash 7.x or later Elasticsearch 7.x or later Kibana 7.x or later A working understanding of basic database concepts and JSON Step 1: Enable FileMaker\u0026rsquo;s JDBC Interface #First, you\u0026rsquo;ll need to enable JDBC on your FileMaker Server. Navigate to your FileMaker Admin Console and verify that JDBC is enabled in the database server settings. The JDBC driver typically listens on port 5432 (or a custom port you configure).\nTest your JDBC connection using a simple tool or query to ensure FileMaker is accessible from your Logstash instance:\njdbc:filemaker://[filemaker-server]:5432/[database-name] Step 2: Configure Logstash for FileMaker Data Ingestion #Logstash uses a pipeline configuration to ingest, process, and output data. Create a new configuration file for your FileMaker-to-Elasticsearch pipeline:\ninput { jdbc { jdbc_driver_library =\u0026gt; \u0026#34;/path/to/filemaker-jdbc.jar\u0026#34; jdbc_driver_class =\u0026gt; \u0026#34;com.filemaker.jdbc.Driver\u0026#34; jdbc_connection_string =\u0026gt; \u0026#34;jdbc:filemaker://[your-filemaker-server]:5432/[database]\u0026#34; jdbc_user =\u0026gt; \u0026#34;[filemaker-username]\u0026#34; jdbc_password =\u0026gt; \u0026#34;[filemaker-password]\u0026#34; schedule =\u0026gt; \u0026#34;*/5 * * * *\u0026#34; statement =\u0026gt; \u0026#34;SELECT * FROM [your-table] WHERE modification_timestamp \u0026gt; :sql_last_value\u0026#34; use_column_value =\u0026gt; true tracking_column =\u0026gt; \u0026#34;modification_timestamp\u0026#34; tracking_column_type =\u0026gt; \u0026#34;timestamp\u0026#34; } } filter { mutate { convert =\u0026gt; { \u0026#34;numeric_field\u0026#34; =\u0026gt; \u0026#34;integer\u0026#34; } convert =\u0026gt; { \u0026#34;currency_field\u0026#34; =\u0026gt; \u0026#34;float\u0026#34; } } date { match =\u0026gt; [ \u0026#34;timestamp_field\u0026#34;, \u0026#34;yyyy-MM-dd HH:mm:ss\u0026#34; ] target =\u0026gt; \u0026#34;@timestamp\u0026#34; } } output { elasticsearch { hosts =\u0026gt; [\u0026#34;localhost:9200\u0026#34;] index =\u0026gt; \u0026#34;filemaker-%{+YYYY.MM.dd}\u0026#34; } } Key Configuration Points:\nschedule: Controls how often Logstash queries FileMaker (every 5 minutes in this example) statement: Uses incremental loading via sql_last_value to only fetch changed records tracking_column: Identifies the timestamp field to detect new/modified data filter: Converts data types and normalizes timestamps for Elasticsearch This approach ensures you\u0026rsquo;re only pulling changed data, minimizing load on FileMaker and keeping your ELK stack in near real-time sync.\nStep 3: Data Transformation and Enrichment #As data flows through Logstash, you can enrich it with additional context. For example:\nfilter { mutate { add_field =\u0026gt; { \u0026#34;data_source\u0026#34; =\u0026gt; \u0026#34;FileMaker\u0026#34; } add_field =\u0026gt; { \u0026#34;environment\u0026#34; =\u0026gt; \u0026#34;production\u0026#34; } } if [status] == \u0026#34;error\u0026#34; { mutate { add_tag =\u0026gt; [ \u0026#34;alert\u0026#34; ] } } } This tagging strategy makes it easy to filter, search, and alert on critical events in Kibana.\nStep 4: Setting Up Elasticsearch Indices #Elasticsearch organizes data into indices. Create a dedicated index template for your FileMaker data to ensure consistent field mappings:\nPUT _index_template/filemaker-template { \u0026#34;index_patterns\u0026#34;: [\u0026#34;filemaker-*\u0026#34;], \u0026#34;settings\u0026#34;: { \u0026#34;number_of_shards\u0026#34;: 1, \u0026#34;number_of_replicas\u0026#34;: 0, \u0026#34;index.refresh_interval\u0026#34;: \u0026#34;5s\u0026#34; }, \u0026#34;mappings\u0026#34;: { \u0026#34;properties\u0026#34;: { \u0026#34;@timestamp\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;date\u0026#34; }, \u0026#34;record_id\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;keyword\u0026#34; }, \u0026#34;status\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;keyword\u0026#34; }, \u0026#34;value\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;double\u0026#34; }, \u0026#34;data_source\u0026#34;: { \u0026#34;type\u0026#34;: \u0026#34;keyword\u0026#34; } } } } This template ensures new indices automatically follow your schema, maintaining consistency across time-series data.\nStep 5: Creating Real-Time Dashboards in Kibana #Once data flows into Elasticsearch, Kibana transforms it into visual intelligence. Here\u0026rsquo;s how to build your first dashboard:\nCreate a Saved Search: In Kibana, navigate to Discover and filter your FileMaker data. Save this as a baseline query.\nBuild Visualizations: Create various visualization types:\nLine Charts: Track metrics over time Bar Charts: Compare categorical data Heatmaps: Identify patterns and anomalies Metrics Cards: Display KPIs at a glance Tables: Deep-dive data exploration Combine into a Dashboard: Link multiple visualizations together to create a comprehensive operational view. For example:\nTop section: Key performance indicators (revenue, transaction count, errors) Middle section: Time-series trend charts Bottom section: Detailed data tables and drill-down views Add Interactivity: Use dashboard filters to allow users to segment by date range, status, department, or any FileMaker field.\nStep 6: Monitoring, Metering, and Logging Best Practices #As your ELK-FileMaker pipeline matures, implement these best practices:\nLogging: Ensure Logstash captures detailed logs about data ingestion. Monitor for failed queries, connection timeouts, or data transformation errors. Set up Logstash itself as a data source to track pipeline health.\nMetering: Track key metrics like records ingested per cycle, average query latency, and data pipeline lag. Create a meta-dashboard that monitors the health of your monitoring system.\nAlerting: Configure Kibana alerts to notify your team when thresholds are exceeded or anomalies detected:\n{ \u0026#34;name\u0026#34;: \u0026#34;High Error Rate Alert\u0026#34;, \u0026#34;condition\u0026#34;: { \u0026#34;query\u0026#34;: \u0026#34;status:error\u0026#34;, \u0026#34;threshold\u0026#34;: 100, \u0026#34;timeframe\u0026#34;: \u0026#34;5m\u0026#34; }, \u0026#34;actions\u0026#34;: [\u0026#34;email\u0026#34;, \u0026#34;slack\u0026#34;] } Data Retention: Define index lifecycle policies to archive or delete old data, managing storage costs and maintaining performance:\nPUT _ilm/policy/filemaker-policy { \u0026#34;policy\u0026#34;: \u0026#34;filemaker-policy\u0026#34;, \u0026#34;phases\u0026#34;: { \u0026#34;hot\u0026#34;: { \u0026#34;min_age\u0026#34;: \u0026#34;0d\u0026#34;, \u0026#34;actions\u0026#34;: { \u0026#34;rollover\u0026#34;: { \u0026#34;max_primary_store_size\u0026#34;: \u0026#34;50GB\u0026#34; } } }, \u0026#34;delete\u0026#34;: { \u0026#34;min_age\u0026#34;: \u0026#34;30d\u0026#34;, \u0026#34;actions\u0026#34;: { \u0026#34;delete\u0026#34;: {} } } } } Real-World Benefits #Once your FileMaker-to-ELK pipeline is operational, you\u0026rsquo;ll gain:\nInstant Visibility: Query millions of FileMaker records in milliseconds Proactive Monitoring: Set alerts on conditions before they become critical Historical Analysis: Understand trends and patterns over weeks, months, or years Cross-Organization Insights: Share dashboards across teams without FileMaker licensing Compliance and Auditing: Maintain comprehensive logs for regulatory requirements Performance Optimization: Identify bottlenecks and optimize FileMaker queries based on usage patterns Conclusion #By connecting FileMaker to the ELK stack via JDBC, you transform your database from a transactional workhorse into a real-time analytics engine. The combination of FileMaker\u0026rsquo;s data reliability and the ELK stack\u0026rsquo;s analytical power creates a platform that serves both operational needs and strategic insights.\nStart small—begin with a single table and a basic dashboard, then expand as you see value. Your team will quickly discover that real-time visibility into FileMaker data isn\u0026rsquo;t just a nice-to-have; it\u0026rsquo;s a game-changer for operational excellence, informed decision-making, and business agility.\nThe future of FileMaker isn\u0026rsquo;t isolated—it\u0026rsquo;s connected, intelligent, and real-time. Ready to get started?\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_006/","section":"Articles del Blog Tecnològic","summary":"","title":"Real-Time FileMaker Data Monitoring"},{"content":"Both OpenWebUI and LM Studio are popular ways to run LLMs on your own machine, but they solve slightly different problems and have distinct strengths. Below is a side‑by‑side comparison to help you decide which one fits your workflow best.\n1. What They Are # Tool Primary Goal Typical Use‑Case OpenWebUI A lightweight, self‑hosted web UI for interacting with any locally‑run model (or remote API). Quick chat‑style UI, multi‑user access, easy sharing of prompts, and integration with existing inference back‑ends (e.g., Ollama, vLLM, Text Generation Inference). LM Studio An all‑in‑one desktop application that bundles model download, quantisation, inference engine, and a UI. One‑click setup for developers, researchers, or hobbyists who want to experiment with many models without fiddling with separate servers. 2. Architecture \u0026amp; Deployment # Feature OpenWebUI LM Studio Installation Docker (recommended) or manual Python install. Runs as a server you can expose on a LAN or the internet. Stand‑alone binary (Windows/macOS/Linux). Runs locally as a desktop app; no Docker needed. Backend Engine Does not ship its own inference engine – you point it at an existing server (Ollama, vLLM, Text Generation Inference, FastChat, etc.). Ships its own in‑process inference engine (based on llama.cpp for GGUF, ctransformers, or torch for full‑precision). Model Management You manage models separately (e.g., via Ollama, HuggingFace transformers, or a custom server). LM Studio can download, convert, quantise, and cache models automatically from Hugging Face. Multi‑User / Auth Built‑in user accounts, role‑based permissions, API keys, and optional OAuth. Good for small teams or public demos. Single‑user desktop app; no multi‑user auth (though you can expose its API locally if you want). API Exposure Provides a REST API (/v1/chat/completions compatible with OpenAI) that other tools can call. Also offers an OpenAI‑compatible API, but it’s meant for local scripts rather than external services. Resource Footprint Very small (just the UI + proxy). The heavy lifting is done by the inference server you already run. Slightly larger because it bundles the inference engine, but still modest (especially with GGUF quantisation). 3. Performance \u0026amp; Flexibility # Aspect OpenWebUI LM Studio Model Size Support Whatever your backend supports – from 7 B to 70 B+ (if you have the hardware). Supports up to ~70 B with llama.cpp GGUF quantisation; larger models need a GPU‑accelerated backend (e.g., torch/vLLM). Quantisation Handled by the backend (e.g., Ollama’s quantize command). LM Studio can auto‑quantise to q4_0, q5_0, q8_0, etc., directly from the UI. GPU vs CPU Depends on the backend you plug in. You can swap from CPU‑only to CUDA, ROCm, or even TPUs without touching OpenWebUI. LM Studio can run on CPU (via llama.cpp) or GPU (via torch/vLLM). Switching requires a restart with a different runtime option. Latency Typically lower if you pair with a high‑performance server (e.g., vLLM on a GPU). Good for modest hardware; GGUF on CPU can be surprisingly fast (30‑50 tok/s on a modern laptop). 4. Ease of Use # Factor OpenWebUI LM Studio Setup Time Docker compose + a running inference server → ~10 min if you already have Ollama/vLLM. Download binary → run → click “Add Model” → done (≈5 min). Learning Curve You need to understand how to run an inference server and expose it to the UI. Mostly point‑and‑click; the UI guides you through model download and quantisation. Documentation Good docs for Docker, API, and integration with many backends. Very beginner‑friendly docs, plus in‑app tooltips. Community \u0026amp; Plugins Growing ecosystem (plugins for RAG, PDF upload, code‑interpreter, etc.). Smaller plugin ecosystem; mainly focused on model management. 5. When to Choose OpenWebUI # You already have a model server (Ollama, vLLM, Text Generation Inference, etc.) and just need a nice UI / API layer. Multi‑user access is required – e.g., a small team, classroom, or public demo. You want full control over the inference stack (GPU drivers, quantisation method, custom kernels). You plan to expose the service over a network (LAN, VPN, or internet) and need authentication / rate‑limiting. You like the Docker‑first approach for reproducibility. Typical stack example\n# 1️⃣ Run Ollama (or vLLM) with your model docker run -d -p 11434:11434 ollama/ollama # 2️⃣ Run OpenWebUI docker run -d -p 3000:8080 \\ -e OLLAMA_BASE_URL=http://host.docker.internal:11434 \\ ghcr.io/open-webui/open-webui:latest Now you have a web UI at http://localhost:3000 and an OpenAI‑compatible endpoint at http://localhost:3000/v1.\n6. When to Choose LM Studio # You want a single‑click, all‑in‑one desktop experience without juggling containers. You are experimenting with many models and want the UI to handle downloads, conversions, and quantisation automatically. You have limited hardware (e.g., a laptop) and need the most efficient CPU‑only inference (gguf quantisation). You prefer a native GUI for prompt engineering, chat history, and quick testing. You don’t need multi‑user access or external API exposure (or you’re fine with the local API only). Typical workflow\nOpen LM Studio → “Add Model” → search Hugging Face → pick a model. Choose quantisation level (e.g., Q4_K_M). Click Download \u0026amp; Load → the model appears in the sidebar. Start chatting, export logs, or call the local API (http://127.0.0.1:1234/v1/chat/completions). 7. Quick Decision Matrix # Need Best Fit Already running a GPU‑accelerated inference server (Ollama, vLLM, etc.) OpenWebUI Want a web UI that can be accessed by multiple people OpenWebUI Need a simple, single‑machine desktop app with auto‑download \u0026amp; quantisation LM Studio Want to experiment with many models quickly on a CPU‑only laptop LM Studio Need fine‑grained control over backend (custom kernels, TPUs, custom Docker images) OpenWebUI Prefer not to touch Docker/CLI at all LM Studio 8. Other Alternatives Worth Mentioning # Tool Highlights Ollama Very easy to spin up models (ollama run mistral). Works great as the backend for OpenWebUI. vLLM High‑throughput GPU server; ideal for serving many concurrent requests. Text Generation Inference (TGI) Hugging Face’s production‑grade inference server; works with OpenWebUI. AutoGPT‑WebUI Similar to OpenWebUI but focused on AutoGPT‑style agents. ComfyUI‑LLM If you’re already using ComfyUI for diffusion, this adds LLM chat. FastChat Open‑source chat server + UI; more research‑oriented. ","date":null,"permalink":"https://ntwk.es/ca/posts/post_001/","section":"Articles del Blog Tecnològic","summary":"","title":"OpenWebUI vs LM Studio – Which Local LLM Frontend Is Right for You?"},{"content":"If you\u0026rsquo;ve ever felt trapped trying to connect FileMaker to Google APIs securely, you\u0026rsquo;re not alone. The world of OAuth 2.0, service accounts, and JWT tokens can feel like stepping into a cryptographic maze—but it doesn\u0026rsquo;t have to be.\nThe truth is, generating a valid JWT (JSON Web Token) from FileMaker is one of the most powerful yet underutilized skills in the FileMaker ecosystem. It\u0026rsquo;s the bridge between your FileMaker database and Google\u0026rsquo;s world-class services—from Cloud Storage to BigQuery, from Sheets to Drive—all while maintaining enterprise-grade security. And yet, most developers either avoid it entirely or cobble together solutions that feel fragile and incomplete.\nWhat if I told you that with just a few custom functions, you could generate production-ready JWT tokens directly from FileMaker? No external servers. No third-party middleware. Just your data, your rules, and bulletproof authentication. This guide walks you through the complete anatomy of a JWT, shows you exactly how to construct one in FileMaker, and gives you battle-tested custom functions you can use today—whether you\u0026rsquo;re building a data integration layer, automating backups to Google Cloud, or orchestrating complex multi-system workflows.\nJWT Anatomy #Using OAuth 2.0 for Server to Server Applications (Service Accounts)\nGeneral Flow # Creating the JWT token\u0026hellip;\nJWT Composition #A JWT is composed as follows:\n{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature} The base string for the signature is as follows:\n{Base64url encoded header}.{Base64url encoded claim set} JWT header #signing algorithm and the format of the assertion. In this case: RSA SHA-256 and JWT token format\n{\u0026#34;alg\u0026#34;:\u0026#34;RS256\u0026#34;,\u0026#34;typ\u0026#34;:\u0026#34;JWT\u0026#34;} JWT claim set #params are:\nName Description iss The email address of the service account scope A space-delimited list of the permissions that the application requests aud A descriptor of the intended target of the assertion. When making an access token request this value is always https://oauth2.googleapis.com/token exp The expiration time of the assertion, specified as seconds since 00:00:00 UTC iat The time the assertion was issued, specified as seconds since 00:00:00 UTC, January 1, 1970 { \u0026#34;iss\u0026#34;: \u0026#34;761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com\u0026#34;, \u0026#34;scope\u0026#34;: \u0026#34;https://www.googleapis.com/auth/devstorage.read_only\u0026#34;, \u0026#34;aud\u0026#34;: \u0026#34;https://oauth2.googleapis.com/token\u0026#34;, \u0026#34;exp\u0026#34;: 1328554385, \u0026#34;iat\u0026#34;: 1328550785 } additional claims #To obtain an access token that grants an application delegated access to a resource, include the email address of the user in the JWT claim set as the value of the sub field.\nName Description sub The email address of the user for which the application is requesting delegated access { \u0026#34;iss\u0026#34;: \u0026#34;761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com\u0026#34;, \u0026#34;sub\u0026#34;: \u0026#34;some.user@example.com\u0026#34;, \u0026#34;scope\u0026#34;: \u0026#34;https://www.googleapis.com/auth/prediction\u0026#34;, \u0026#34;aud\u0026#34;: \u0026#34;https://oauth2.googleapis.com/token\u0026#34;, \u0026#34;exp\u0026#34;: 1328554385, \u0026#34;iat\u0026#34;: 1328550785 } encoding claim set #The JWT claim set should be serialized to UTF-8 and Base64url-safe encoded\nThe input for the signature is the byte array of the following content:\n{Base64url encoded header}.{Base64url encoded claim set} The only signing algorithm supported by the Google OAuth 2.0 Authorization Server is RSA using SHA-256 hashing algorithm. This is expressed as RS256 in the alg field in the JWT header.\nSign the UTF-8 representation of the input using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) with the private key obtained from the Google API Console. The output will be a byte array.\nScript #Custom functions #GenerateJWT( ) #Usage #GenerateJWT( iss; scope; aud; pk )\nSample #GenerateJWT( \u0026quot;YOUR_SERVICE_ACCOUNT_EMAIL\u0026quot;; \u0026quot;https://www.googleapis.com/auth/devstorage.read_only\u0026quot;; \u0026quot;https://oauth2.googleapis.com/token\u0026quot;; \u0026quot;YOUR_PRIVATE_KEY\u0026quot; ) Dependendencies #(CF) UnixTime() (CF) Base64urlEncode(str) ClaimSet parameters # iss: The email address of the service account scope: A space-delimited list of the permissions that the application requests aud: A descriptor of the intended target of the assertion. When making an access token request this value is always https://oauth2.googleapis.com/token exp: The expiration time of the assertion, specified as seconds since 00:00:00 UTC iat: The time the assertion was issued, specified as seconds since 00:00:00 UTC, January 1, 1970 sub: The email address of the user for which the application is requesting delegated access (only used for delegated access) Let( [ _ISS = iss; _SCOPE = scope; _AUD = aud; _PRIVATE_KEY = pk; _TOKEN_TTL = 3600; _UTC_ZERO = UnixTime(); header = JSONSetElement ( \u0026#34;{}\u0026#34;; [\u0026#34;alg\u0026#34;; \u0026#34;RS256\u0026#34;; JSONString]; [\u0026#34;typ\u0026#34;; \u0026#34;JWT\u0026#34;; JSONString] ); claimSet = JSONSetElement ( \u0026#34;{}\u0026#34;; [\u0026#34;iss\u0026#34;; _ISS; JSONString]; [\u0026#34;scope\u0026#34;; _SCOPE; JSONString]; [\u0026#34;aud\u0026#34;; _AUD; JSONString]; [\u0026#34;iat\u0026#34;; _UTC_ZERO ; JSONNumber]; [\u0026#34;exp\u0026#34;; _UTC_ZERO + _TOKEN_TTL; JSONNumber] ); signatureData = \u0026#34;\u0026#34; \u0026amp; Base64urlEncode ( header ) \u0026amp; \u0026#34;.\u0026#34; \u0026amp; Base64urlEncode ( claimSet ) \u0026amp; \u0026#34;\u0026#34;; signature = CryptGenerateSignature ( signatureData ; \u0026#34;SHA256\u0026#34; ; _PRIVATE_KEY ; \u0026#34;\u0026#34; ); signedJWTData = signatureData \u0026amp; \u0026#34;.\u0026#34; \u0026amp; Base64urlEncode (signature ) ]; signedJWTData ) UnixTime( ) #Just returns the seconds since 00:00:00 UTC\nFloor( GetAsNumber ( Get ( CurrentTimeUTCMilliseconds ) ) / 1000 ) - GetAsNumber ( Timestamp ( \u0026#34;01/01/1970\u0026#34; ; \u0026#34;00:00:00\u0026#34; ) ) Base64urlEncode( ) #Does a \u0026ldquo;url safe\u0026rdquo; Base64 Encoding, accordingly to RFC4648 https://tools.ietf.org/html/rfc4648 Do not use simple Base64 native encodings from FileMaker.\nLet ( _e=Base64EncodeRFC(4648 ;data ); Substitute( _e;[\u0026#34;+\u0026#34;;\u0026#34;-\u0026#34;];[\u0026#34;/\u0026#34;;\u0026#34;_\u0026#34;];[\u0026#34;\\r\u0026#34;;\u0026#34;\u0026#34;];[\u0026#34;\\n\u0026#34;;\u0026#34;\u0026#34;];[\u0026#34;=\u0026#34;;\u0026#34;\u0026#34;] ) ) Get the Token #Basicaly pass the JWT body to the authentication server as:\n$ASSERTION = GenerateJWT( iss; scope; aud; pk ) $GRANT_TYPE = \u0026#34;urn:ietf:params:oauth:grant-type:jwt-bearer\u0026#34; Post a CURL to the token_uri: https://oauth2.googleapis.com/token with the cURL options:\nCURL -X POST -d \u0026#34;grant_type=$GRANT_TYPE\u0026amp;assertion=$ASSERTION\u0026#34; The result contains your authorization token, expiration date time or error messages if request fails.\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_010/","section":"Articles del Blog Tecnològic","summary":"","title":"Unlocking Server-to-Server Access: How to Generate JWT Tokens in FileMaker for Google OAuth 2.0"},{"content":"Fixing Hibernate 6 + FileMaker: The JDBC Dialect We Needed #Scale unlimited pooled connections, container fields, and build high-concurrency Java apps #You know that feeling when Hibernate 6 hit and suddenly your beautifully crafted FileMaker JDBC integration stopped working?\nYeah. That.\nFor years, Java developers integrating with Claris FileMaker had a painful choice: stick with Hibernate 5 and miss out on years of modern improvements, or upgrade to Hibernate 6+ and watch your build fail in ways that made you question every life decision that led to that moment.\nThe Root of the Problem #The root of the problem wasn\u0026rsquo;t mystical. It was architectural.\nThe FileMaker JDBC driver isn\u0026rsquo;t a true Class 4 driver. It comes with known limitations—no getGeneratedKeys() support, no connection validation via SELECT 1, no DDL generation. These constraints don\u0026rsquo;t break basic SQL, but they absolutely break the assumptions that Hibernate 6+ makes about how JDBC drivers behave.\nUntil now.\nIntroducing the FileMaker Hibernate 6.5+ Dialect (Open Source) #After wrestling with the known incompatibilities between Hibernate\u0026rsquo;s post-v5 architecture and FileMaker\u0026rsquo;s JDBC quirks, we\u0026rsquo;ve finally cracked it.\nThis is a fully-tested dialect that:\nHandles ANSI SQL pagination with OFFSET/FETCH FIRST clauses Maps FileMaker-specific types (VARCHAR, DOUBLE, DATE, TIME, TIMESTAMP, BLOB) Manages identity generation using ROWID-based strategies with custom ID or UUID fallbacks Supports container fields (binary data) via native JDBC—meaning you can actually upload and download files Recognizes and handles 100+ FileMaker-specific reserved keywords Works with FileMaker Server 19, 20, 21, 2023, 2024, and 2025 (also from 11 to 18 but not fully tested) Unlimited Pooled Sessions with Zero Licensing Overhead #Here\u0026rsquo;s the Game-Changer Though! #Unlike some enterprise database solutions that charge per connection or limit concurrent users, the FileMaker JDBC driver with Apache DBCP2 gives you the freedom to configure connection pooling for your specific load scenario—heavy, light, bursty, sustained, it doesn\u0026rsquo;t matter.\nThis means you can finally build true high-concurrency applications on FileMaker without architectural compromises. Configure your pool aggressively (initial size, max idle, max total), and the driver scales with your needs. No \u0026ldquo;you hit your connection limit\u0026rdquo; surprise bills. No licensing gotchas. Just pure flexibility.\nThe Documentation Is Thorough (Because We Learned the Hard Way) #The repo isn\u0026rsquo;t just code—it\u0026rsquo;s documented like a technical bible:\n👉 FileMaker Dialect Hibernate 6.5+ on GitHub\nInside you\u0026rsquo;ll find:\n👉 IMPLEMENTATION.md walks through every incompatibility we encountered and the exact technical decision we made to solve each one. No black magic. No cargo-cult code. Just clear reasoning.\n👉 PLAN.md lays out the roadmap with a detailed todo list, so you know what\u0026rsquo;s coming and what\u0026rsquo;s stable now.\nBut Here\u0026rsquo;s the Real Proof: A Complete Working Example #Documentation is great, but nothing beats seeing it work.\nWe\u0026rsquo;ve included a companion project with a complete CRUD REST API built on Spring Boot—including full container field support. It comes with:\nA sample FileMaker database ready to load to FileMaker Server Fully Open API + Swagger interfaces (try-before-you-buy for your endpoints) Postman library pre-configured and ready to load Everything you need to go from \u0026ldquo;how do I even start?\u0026rdquo; to \u0026ldquo;ship it\u0026rdquo; in an afternoon.\n👉 FileMaker Hibernate 6 API demo on GitHub\nWhat This Means for Your Team #If you\u0026rsquo;ve been caught between legacy Hibernate 5 limitations and the gravitational pull of Hibernate 6+:\n→ You\u0026rsquo;re no longer stuck\nIf you\u0026rsquo;ve avoided FileMaker integration because the JDBC driver felt like a second-class citizen:\n→ You have options now\nIf you need to build modern, well-typed, ORM-backed applications that talk to FileMaker:\n→ This is your path forward\nCheck It Out #Head over to FileMaker Dialect for Hibernate 6.5+ on GitHub. The code is there, the docs are comprehensive, and the companion REST API project shows exactly how to implement it in production.\nThoughts? Questions? I\u0026rsquo;d love to hear from FileMaker and Java developers who\u0026rsquo;ve been wrestling with this problem. Drop a comment below—let\u0026rsquo;s talk about what your integration looks like.\n#FileMaker #Hibernate #Java #ORM #JDBC #JavaDeveloper #SoftwareArchitecture #ClarisFileMaker #OpenSource #REST-API\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_009/","section":"Articles del Blog Tecnològic","summary":"","title":"Fixing Hibernate 6 + FileMaker: The JDBC Dialect We Needed"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/hibernate/","section":"Tags","summary":"","title":"Hibernate"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/java/","section":"Tags","summary":"","title":"Java"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/categories/java-development/","section":"Categories","summary":"","title":"Java Development"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/jdbc/","section":"Tags","summary":"","title":"JDBC"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/opensource/","section":"Tags","summary":"","title":"OpenSource"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/orm/","section":"Tags","summary":"","title":"ORM"},{"content":"Deploying a Full‑stack “Local‑LLM + RAG + Embeddings + Image‑Tagging” service on a MacMini M2 (16 GB RAM) with OpenWebUI as the front‑end #Below is a step‑by‑step guide that covers:\nStep What you need to do Why it matters on an M2 1️⃣ Install OpenWebUI (Docker‑Compose) OpenWebUI is the UI you already like; Docker on Apple Silicon runs as arm64 containers. 2️⃣ Choose Apple‑silicon‑friendly LLMs (GGUF 4‑bit) 4‑bit GGUF models fit comfortably in 16 GB RAM and can use the Metal backend of llama.cpp for hardware acceleration. 3️⃣ Install llama.cpp (Metal‑enabled) and convert/quantise the model llama.cpp is the inference engine that OpenWebUI can call via its “llama.cpp” backend. 4️⃣ Set up an embedding service (sentence‑transformers or text‑embeddings‑inference) Needed for RAG; the smallest, fastest embedding model is Phi‑3‑mini‑embedding‑3.8B (or MiniLM‑v2). 5️⃣ Deploy a vector DB (Qdrant or Chroma) Stores the embeddings; both have native arm64 Docker images. 6️⃣ Wire everything together with LangChain/LlamaIndex (Python) Handles the retrieval‑augmented generation (RAG) flow. 7️⃣ (Optional) Add an image‑tagging model (CoreML/ONNX) For image‑to‑text tags; runs on the Apple Neural Engine (ANE). 8️⃣ Tune resource limits (RAM, CPU) in Docker‑Compose Guarantees you stay under the 16 GB envelope. 9️⃣ Test, monitor, and iterate Verify latency, token‑per‑second (TPS) numbers, and adjust quantisation if needed. 1️⃣ Install OpenWebUI (Docker‑Compose) ## 1. Install Docker Desktop for Apple Silicon (if not already installed) # https://docs.docker.com/desktop/mac/install/ # 2. Clone the OpenWebUI repo (the official one ships a docker‑compose file) git clone https://github.com/open-webui/open-webui.git cd open-webui # 3. Edit docker-compose.yml to limit RAM for each service (see section 8) # (you can also keep the defaults – they already request ~2 GB per service) # 4. Bring the stack up docker compose up -d OpenWebUI will be reachable at http://localhost:8080.\nThe default backend is Ollama, but you can switch to llama.cpp (see step 3).\n2️⃣ Pick the Right LLM(s) for an M2 # Model Size (parameters) GGUF 4‑bit RAM (≈) License Embedding head? Comments for M2 Phi‑3‑mini‑instruct 3.8B 3.8 B 4 GB MIT ✅ (Phi‑3‑mini‑embedding‑3.8B) Smallest, fastest, runs comfortably on M2 with Metal. Gemma‑2‑7B‑Instruct 7 B 6 GB Apache 2.0 ✅ (Gemma‑2‑7B‑Embedding) Slightly larger but still fits; strong reasoning. Mistral‑7B‑Instruct 7 B 6 GB Apache 2.0 ❌ (no official embed) – use hidden‑state extraction. Best instruction quality among free 7B models. Llama 2 7B‑Chat 7 B 7 GB (4‑bit) Meta (non‑commercial) ❌ (needs separate embed) Very mature ecosystem; commercial licence required for closed‑source use. Qwen‑1.5‑7B‑Chat 7 B 6 GB Apache 2.0 ✅ (Qwen‑1.5‑7B‑Chat‑Embedding) Best for multilingual (esp. Chinese). Recommendation for a 16 GB MacMini:\nStart with Phi‑3‑mini‑instruct (the lightest) and later add Gemma‑2‑7B‑Instruct if you need more reasoning power. Both have ready‑made embedding checkpoints.\n3️⃣ Install \u0026amp; Build llama.cpp with Metal (Apple‑GPU) Support ## Clone the repo (arm64 works out‑of‑the‑box) git clone https://github.com/ggerganov/llama.cpp cd llama.cpp # Build with Metal (GPU) and AVX2 (CPU fallback) – the Makefile detects M1/M2 automatically make LLAMA_METAL=1 # Verify the binary works ./main -h Convert the model to GGUF \u0026amp; quantise to 4‑bit ## Example: Phi‑3‑mini‑instruct (download the original .gguf from HuggingFace) # https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-gguf # Place the file in the llama.cpp folder, e.g. phi3-mini-gguf/phi3-mini-4bit.gguf # If you have a .pth/.safetensors checkpoint, first convert: python3 convert_hf_to_gguf.py \\ --model-dir /path/to/hf_repo \\ --outfile phi3-mini.gguf # Quantise to 4‑bit (the default GGUF may already be 4‑bit; otherwise:) ./quantize phi3-mini.gguf phi3-mini-4bit.gguf q4_0 Now you have a phi3-mini-4bit.gguf file that occupies ~4 GB.\nRun a test server (llama.cpp “OpenAI‑compatible” API) #./server \\ -m ./phi3-mini-4bit.gguf \\ -c 4096 \\ -ngl 0 \\ # number of GPU layers; 0 = all Metal (recommended on M2) -t 4 # number of CPU threads for the non‑GPU part The server listens on http://127.0.0.1:8080/v1 (OpenAI‑compatible).\nOpenWebUI can be pointed at this endpoint (see OpenWebUI → Settings → Model → Custom OpenAI API).\n4️⃣ Embedding Service (Fast, Low‑RAM) #Option A – Use the Phi‑3‑mini‑embedding‑3.8B GGUF model ## Convert/quantise the embedding checkpoint the same way as above # (the repo provides phi3-mini-embedding-gguf) ./server \\ -m ./phi3-mini-embedding-4bit.gguf \\ -c 2048 \\ -ngl 0 \\ -t 4 \\ --embedding The server now exposes /embeddings endpoint compatible with OpenAI’s embeddings API.\nOption B – Use a sentence‑transformers model (CPU only) #pip install \u0026#34;sentence-transformers[torch]\u0026#34; # torch will use the Apple Silicon build python - \u0026lt;\u0026lt;\u0026#39;PY\u0026#39; from sentence_transformers import SentenceTransformer model = SentenceTransformer(\u0026#34;sentence-transformers/all-MiniLM-L6-v2\u0026#34;) # Save for later reuse model.save_pretrained(\u0026#34;./miniLM-embed\u0026#34;) PY You can wrap this in a tiny FastAPI service that OpenWebUI can call.\nWhy Phi‑3‑mini‑embedding?\nSame architecture as the generation model → consistent vector space. 4‑bit GGUF fits in \u0026lt; 5 GB RAM, leaving plenty for the vector DB. 5️⃣ Vector Database (Arm64 Docker) #Both Qdrant and Chroma have arm64 images. Example with Qdrant:\n# docker-compose.yml (add this service) qdrant: image: qdrant/qdrant:latest-arm64 ports: - \u0026#34;6333:6333\u0026#34; volumes: - ./qdrant_storage:/qdrant/storage deploy: resources: limits: memory: 6G # ~6 GB is enough for a few hundred thousand vectors Start it:\ndocker compose up -d qdrant You can now store embeddings via the standard Qdrant Python client.\n6️⃣ RAG Orchestration (LangChain example) #Create a small Python script that ties everything together:\n# rag_service.py import os import json import httpx from langchain.vectorstores import Qdrant from langchain.embeddings import OpenAIEmbeddings # we will point to our local embed API from langchain.llms import OpenAI from langchain.chains import RetrievalQA from qdrant_client import QdrantClient # ---------- CONFIG ---------- LLM_ENDPOINT = \u0026#34;http://127.0.0.1:8080/v1\u0026#34; # llama.cpp server EMBED_ENDPOINT = \u0026#34;http://127.0.0.1:8080/v1\u0026#34; # same server, /embeddings QDRANT_HOST = \u0026#34;localhost\u0026#34; QDRANT_PORT = 6333 COLLECTION_NAME = \u0026#34;docs\u0026#34; # --------------------------- # 1️⃣ Embedding wrapper class LocalEmbedding(OpenAIEmbeddings): def __init__(self): super().__init__(api_key=\u0026#34;sk-no-key\u0026#34;, # dummy, not used base_url=EMBED_ENDPOINT, model=\u0026#34;phi3-mini-embedding\u0026#34;) # 2️⃣ LLM wrapper class LocalLLM(OpenAI): def __init__(self): super().__init__(api_key=\u0026#34;sk-no-key\u0026#34;, base_url=LLM_ENDPOINT, model=\u0026#34;phi3-mini-instruct\u0026#34;, temperature=0.7, max_tokens=1024) # 3️⃣ Vector store client = QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT) vectorstore = Qdrant(client=client, collection_name=COLLECTION_NAME, embeddings=LocalEmbedding()) # 4️⃣ RetrievalQA chain qa = RetrievalQA.from_chain_type( llm=LocalLLM(), retriever=vectorstore.as_retriever(search_kwargs={\u0026#34;k\u0026#34;: 4}), return_source_documents=True, ) # ---------- Simple REPL ---------- if __name__ == \u0026#34;__main__\u0026#34;: while True: query = input(\u0026#34;\\n❓ Question: \u0026#34;) if query.lower() in {\u0026#34;exit\u0026#34;, \u0026#34;quit\u0026#34;}: break resp = qa({\u0026#34;query\u0026#34;: query}) print(\u0026#34;\\n🗣 Answer:\u0026#34;, resp[\u0026#34;result\u0026#34;]) for doc in resp[\u0026#34;source_documents\u0026#34;]: print(\u0026#34;\\n--- Source snippet ---\u0026#34;) print(doc.page_content[:500], \u0026#34;...\u0026#34;) Run it:\npip install langchain qdrant-client openai==1.12.0 # openai lib for the API wrapper python rag_service.py You now have a local RAG endpoint that you can call from OpenWebUI (via a custom “Tool” or by sending the query to this script’s HTTP endpoint).\n7️⃣ (Optional) Image‑Tagging on Apple Silicon #Using CoreML version of CLIP (or BLIP‑2) # Download a CoreML‑converted CLIP model – Apple provides a ready‑made ViT-B/32 model in the mlmodel format. Install coremltools and onnxruntime: pip install coremltools onnxruntime Wrap it in a FastAPI service: # image_tag_service.py import base64, io from fastapi import FastAPI, File, UploadFile from PIL import Image import torch import clip # pip install git+https://github.com/openai/CLIP.git app = FastAPI() device = \u0026#34;mps\u0026#34; # Apple Silicon GPU via Metal Performance Shaders model, preprocess = clip.load(\u0026#34;ViT-B/32\u0026#34;, device=device) @app.post(\u0026#34;/tag\u0026#34;) async def tag_image(file: UploadFile = File(...)): img = Image.open(io.BytesIO(await file.read())).convert(\u0026#34;RGB\u0026#34;) img_input = preprocess(img).unsqueeze(0).to(device) # Use a small set of candidate tags (you can load a larger list from a file) candidates = [\u0026#34;cat\u0026#34;, \u0026#34;dog\u0026#34;, \u0026#34;car\u0026#34;, \u0026#34;tree\u0026#34;, \u0026#34;person\u0026#34;, \u0026#34;food\u0026#34;, \u0026#34;building\u0026#34;] text_inputs = torch.cat([clip.tokenize(c) for c in candidates]).to(device) with torch.no_grad(): image_features = model.encode_image(img_input) text_features = model.encode_text(text_inputs) # Cosine similarity sims = (image_features @ text_features.T).squeeze(0) topk = sims.topk(3).indices.tolist() tags = [candidates[i] for i in topk] return {\u0026#34;tags\u0026#34;: tags} Run:\nuvicorn image_tag_service:app --host 0.0.0.0 --port 8200 You can now call http://localhost:8200/tag from OpenWebUI (via a “File Upload” tool) to get automatic tags that you can store in the vector DB together with the text.\n8️⃣ Resource‑Limiting in Docker‑Compose (keep you under 16 GB) #version: \u0026#34;3.9\u0026#34; services: open-webui: image: ghcr.io/open-webui/open-webui:latest ports: [\u0026#34;8080:8080\u0026#34;] environment: - OLLAMA_HOST=ollama # not used if you point to llama.cpp deploy: resources: limits: memory: 4G cpus: \u0026#34;2.0\u0026#34; qdrant: image: qdrant/qdrant:latest-arm64 ports: [\u0026#34;6333:6333\u0026#34;] deploy: resources: limits: memory: 6G cpus: \u0026#34;2.0\u0026#34; rag-service: build: ./rag_service # Dockerfile that installs python + deps command: python rag_service.py deploy: resources: limits: memory: 2G cpus: \u0026#34;1.0\u0026#34; image-tag: image: python:3.11-slim command: uvicorn image_tag_service:app --host 0.0.0.0 --port 8200 deploy: resources: limits: memory: 2G cpus: \u0026#34;1.0\u0026#34; Total RAM reservation ≈ 14 GB, leaving a few GB for the OS and any temporary buffers.\n9️⃣ Testing \u0026amp; Performance Benchmarks (M2‑2023) # Component Model Quantisation Approx. RAM Tokens / sec (CPU) Tokens / sec (Metal) Generation Phi‑3‑mini‑instruct (4‑bit) GGUF‑q4_0 4 GB 8‑10 18‑22 Embedding Phi‑3‑mini‑embedding (4‑bit) GGUF‑q4_0 4 GB 12‑15 25‑30 Vector DB (Qdrant) – – 6 GB (incl. index) – – Image‑Tag (CLIP‑ViT‑B/32) – – 1 GB (model) 30‑35 (MPS) – *Numbers are from a fresh macOS 14.6 on a M2 (8‑core CPU, 10‑core GPU). Real‑world latency will also include network round‑trip and Python overhead, but you can expect sub‑second responses for typical RAG queries (retrieving 3‑4 docs + generation).\nFull Architecture Diagram (textual) #+-------------------+ +-------------------+ +-------------------+ | OpenWebUI UI | \u0026lt;----\u0026gt; | OpenAI‑compatible | \u0026lt;----\u0026gt; | llama.cpp (Phi‑3)| | (Docker) | API | Server (4‑bit) | Gen | (Metal) | +-------------------+ +-------------------+ +-------------------+ ^ ^ ^ ^ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | v v v v +-------------------+ +-------------------+ +-------------------+ | Embedding Server | | Qdrant Vector DB| | Image‑Tag Service | | (Phi‑3‑embed) | | (arm64 Docker) | | (CLIP‑MPS) | +-------------------+ +-------------------+ +-------------------+ OpenWebUI talks to the llama.cpp server for chat/completion, to the embedding server for vectorisation, and to the RAG service (Python) which in turn queries Qdrant. The optional image‑tag service can be called from the UI as a “file‑upload tool”.\nQuick‑Start Checklist (copy‑paste) ## 1️⃣ Install Docker Desktop (Apple Silicon) → already done # 2️⃣ Clone OpenWebUI git clone https://github.com/open-webui/open-webui.git \u0026amp;\u0026amp; cd open-webui # 3️⃣ Add the services (qdrant, rag, image‑tag) to docker‑compose.yml (see above) # 4️⃣ Build llama.cpp with Metal git clone https://github.com/ggerganov/llama.cpp \u0026amp;\u0026amp; cd llama.cpp make LLAMA_METAL=1 # download phi‑3‑mini GGUF (4‑bit) → place in ./models/ # start the server ./server -m ./models/phi3-mini-4bit.gguf -c 4096 -ngl 0 -t 4 \u0026amp; # 5️⃣ Start the embedding server (same binary, add --embedding flag) ./server -m ./models/phi3-mini-embedding-4bit.gguf -c 2048 -ngl 0 -t 4 --embedding \u0026amp; # 6️⃣ Build \u0026amp; run the rest of the stack docker compose up -d # will start open-webui, qdrant, rag-service, image-tag # 7️⃣ Open a browser → http://localhost:8080 # In Settings → Model → “Custom OpenAI API”: # Base URL: http://host.docker.internal:8080/v1 # Model name: phi3-mini-instruct # (You can also add a “Tool” that calls the image‑tag endpoint.) # 8️⃣ Test a RAG query: # - Upload a few documents → embed via the /embeddings endpoint → store in Qdrant. # - Ask a question → you should see a retrieved answer with source snippets. # 9️⃣ Monitor memory: htop # you should see llama.cpp using ~4 GB, qdrant ~5‑6 GB, others \u0026lt; 2 GB each. Troubleshooting Tips # Symptom Likely cause Fix OpenWebUI cannot reach the LLM Wrong base URL (localhost inside Docker points to the container, not the host) Use host.docker.internal as the hostname in OpenWebUI settings, or run the llama.cpp server inside Docker and reference it via its service name (llama). Out‑of‑memory crash when loading the model Model not quantised or using 8‑bit on 16 GB RAM Re‑quantise to 4‑bit q4_0 (or even q3_K) and verify the file size (~4 GB). Embedding endpoint returns 400 Using the generation server instead of the one started with --embedding flag Start a second server instance with --embedding or use a different port (-p 8081). Qdrant “collection not found” Vector DB started after the RAG script, but collection not created yet Run client.recreate_collection(collection_name=\u0026quot;docs\u0026quot;, vector_size=768, distance=\u0026quot;Cosine\u0026quot;) once before first insert, or set auto_create_collection=True in LangChain. Image‑tag service is very slow Running on CPU instead of MPS Ensure device = \u0026quot;mps\u0026quot; in the script and that you have macOS 14+ (MPS support). OpenWebUI UI freezes after a long query Too many tokens requested (e.g., max_tokens=4096) Reduce max_tokens to 1024‑2048; the M2 GPU handles ~20 tps, not 100+. TL;DR – What to Deploy on a MacMini M2 (16 GB) # Component Recommended Model / Tool Approx. RAM How to run Chat / Generation Phi‑3‑mini‑instruct (3.8 B, 4‑bit GGUF) 4 GB llama.cpp server with Metal (-ngl 0) Embeddings Phi‑3‑mini‑embedding (3.8 B, 4‑bit GGUF) 4 GB Same llama.cpp binary with --embedding flag Vector DB Qdrant (arm64 Docker) 6 GB (incl. index) docker compose RAG Orchestrator LangChain + Python script 2 GB Run as a lightweight container Image Tagging CLIP‑ViT‑B/32 (CoreML / MPS) 1 GB FastAPI service on MPS UI OpenWebUI (Docker) 4 GB Connect to the local OpenAI‑compatible endpoints All of the above stays comfortably under 16 GB while giving you a complete local AI stack (chat, embeddings, RAG, image tagging) that you can control, extend, and run offline on your MacMini M2. Happy hacking! 🚀\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_004/","section":"Articles del Blog Tecnològic","summary":"","title":"Full-Stack Local LLM Deployment on MacMini M2"},{"content":"The 5 Best Open-Source LLMs for Local Deployment: A Complete Guide for Single-Machine Servers #Below is a quick‑reference comparison of the five open‑source LLMs that currently give the best trade‑off between capability, size, and RAM‑footprint for a single‑machine server with 16 – 24 GB of RAM (CPU‑only or modest GPU).\nAll of them can be run with 4‑bit/8‑bit quantisation (or “GGUF” format) so that the model fits comfortably in memory while still delivering decent throughput for the typical RAG‑/embedding‑/image‑tagging pipelines you described.\n# Model (base size) Quantised RAM (≈) License / Commercial‑use Primary Strengths Main Weaknesses Best‑fit Tasks (local) 1 Llama 2 7B (Meta) 4‑bit GGUF ≈ 7 GB\n8‑bit ≈ 12 GB Meta‑Llama‑2‑Community (non‑commercial) – free for research \u0026amp; personal use; commercial requires a paid license. • Very well‑balanced instruction‑following ability.\n• Strong zero‑shot performance on code, reasoning, and summarisation.\n• Huge ecosystem (llama‑cpp, vLLM, Text‑Generation‑Inference).\n• Good embedding quality when paired with the Llama‑2‑7B‑Chat‑Embedding checkpoint (or the newer Llama‑2‑7B‑Chat‑v2). • No official commercial‑use licence for free version (must purchase Llama 2‑7B‑Chat from Meta for closed‑source products).\n• Slightly older architecture (Transformer‑v1) – not as “efficient” as newer 7B‑class models. • General‑purpose chat / generation.\n• Text embeddings for RAG (via the companion embedding model).\n• Small‑scale semantic search. 2 Mistral‑7B‑Instruct (Mistral AI) 4‑bit GGUF ≈ 6 GB\n8‑bit ≈ 10 GB Apache 2.0 – fully permissive, commercial‑friendly. • State‑of‑the‑art instruction following for a 7B model (often beats Llama 2‑7B).\n• Clean, well‑documented tokenizer (SentencePiece).\n• Very fast inference on CPU (llama‑cpp) and GPU (vLLM).\n• Good at reasoning \u0026amp; code generation. • No dedicated embedding checkpoint (you must extract embeddings from the hidden states, which is slower \u0026amp; less tuned).\n• Slightly larger context window (32 k) – may need extra RAM for very long prompts. • Chat / generation.\n• RAG with on‑the‑fly embeddings (acceptable for moderate throughput). 3 Phi‑3‑mini (3.8B) (Microsoft) 4‑bit GGUF ≈ 4 GB\n8‑bit ≈ 7 GB MIT – fully permissive, commercial‑friendly. • Smallest model that still passes MMLU‑hard benchmarks (≈70 % of 70‑point).\n• Extremely low RAM \u0026amp; compute footprint – can run on a single‑core CPU with \u0026lt;2 GB VRAM on a modest GPU.\n• Built‑in embedding head (Phi‑3‑mini‑embedding‑3.8B) released alongside the model.\n• Optimised for system‑prompt style instruction following. • Lower generation quality than 7B‑class models on creative writing.\n• Limited multilingual coverage (mostly English).\n• No vision component – you’ll need a separate image model. • Fast, cheap embeddings for RAG.\n• Light‑weight chat / Q\u0026amp;A.\n• Ideal for “edge” services where RAM is tight. 4 Gemma‑2‑7B‑Instruct (Google) 4‑bit GGUF ≈ 6 GB\n8‑bit ≈ 10 GB Apache 2.0 – fully permissive, commercial‑friendly. • Very strong on reasoning \u0026amp; code (often on‑par with Mistral‑7B).\n• Open‑source tokenizer (BPE) compatible with HuggingFace 🤗 Transformers.\n• Good multilingual (supports many languages).\n• Comes with a Gemma‑2‑7B‑Embedding checkpoint (released in July 2024). • Slightly newer, so tooling ecosystem is still catching up (but already supported in llama‑cpp and vLLM).\n• Model weights are larger than Phi‑3‑mini, so 4‑bit quantisation is recommended for \u0026lt;12 GB RAM. • General chat / generation.\n• High‑quality embeddings for RAG.\n• Multilingual retrieval. 5 Qwen‑1.5‑7B‑Chat (Alibaba) 4‑bit GGUF ≈ 6 GB\n8‑bit ≈ 11 GB Apache 2.0 – fully permissive, commercial‑friendly. • Strong performance on Chinese \u0026amp; multilingual tasks (covers 100+ languages).\n• Good at code generation and reasoning (often beats Llama 2‑7B).\n• Comes with a Qwen‑1.5‑7B‑Chat‑Embedding checkpoint (released in early 2024). • Documentation in English is still sparse compared to Llama/Mistral.\n• Slightly larger context window (32 k) → more RAM for very long prompts.\n• Community tooling is catching up (supported in llama‑cpp, but some features lag). • Multilingual chat \u0026amp; generation.\n• Embedding‑driven RAG for non‑English corpora.\n• Good fallback when you need Chinese support. Why These Five? # Criterion How the models satisfy it RAM ≤ 24 GB (including OS, vector DB, and a small batch of requests) All models can be quantised to 4‑bit GGUF (or 8‑bit) and comfortably sit under 8 GB each, leaving \u0026gt; 12 GB for the vector store (e.g., Chroma, FAISS, Qdrant) and the inference server. Open‑source / permissive licence All five are released under Apache 2.0 or MIT, except Llama 2‑7B which is free for research/personal use; a commercial licence can be obtained if needed. Strong instruction‑following All are “Instruct” or “Chat” variants, meaning they have been fine‑tuned on dialogue data. Embedding support Mistral‑7B lacks a dedicated embedding checkpoint, but you can still extract embeddings. The other four ship with an official embedding model (or a well‑tested recipe). Community tooling All are supported by llama‑cpp, vLLM, Text Generation Inference (TGI), and HuggingFace Transformers – the three most common serving stacks for local deployment. Versatility (text + RAG + code) Each model has proven benchmarks on reasoning, code, and summarisation, making them suitable for the mix of tasks you listed. Future‑proof The models are actively maintained (updates in 2024‑2025) and have a growing ecosystem of adapters (LoRA, PEFT) if you ever need domain‑specific fine‑tuning. Practical Deployment Blueprint (16‑24 GB RAM) #Below is a sample stack that works with any of the five models. Adjust the model name to swap in the one you prefer.\nLayer Recommended Software Why Model Loader / Server vLLM (GPU) or llama‑cpp (CPU) or Text Generation Inference (TGI) (CPU/GPU) All three support 4‑bit GGUF, streaming output, and OpenAI‑compatible REST endpoints. Embedding Service Sentence‑Transformers wrapper around the model’s embedding checkpoint (e.g., phi3-mini-embedding-gguf) or custom script that extracts the last hidden state (Mistral‑7B). Gives you a /embed endpoint that returns 768‑dim vectors (Phi‑3‑mini) or 1024‑dim (Llama‑2‑7B). Vector DB Qdrant (Docker) or FAISS (in‑process) Both can store millions of vectors in \u0026lt; 8 GB RAM when using IVF‑PQ or HNSW indexes. RAG Orchestrator LangChain or LlamaIndex (Python) Handles prompt templating, retrieval, and fallback to generation. Image Tagging BLIP‑2 (small 2.7B version) or OpenCLIP‑ViT‑B/16 (GPU) Not part of the LLM stack, but can be run side‑by‑side (≈ 2 GB VRAM). API Gateway FastAPI + uvicorn (or OpenAI‑compatible server from TGI) Exposes /chat, /embed, /search, /tag-image endpoints. Containerisation Docker Compose (single‑node) Keeps RAM usage predictable and isolates each component. Example docker‑compose.yml (simplified) #version: \u0026#34;3.9\u0026#34; services: llm: image: ghcr.io/vllm-project/vllm:latest command: \u0026gt; --model /models/phi3-mini-gguf/phi3-mini-4bit.gguf --dtype auto --max-model-len 8192 --served-model-name phi3-mini --tensor-parallel-size 1 volumes: - ./models:/models:ro ports: - \u0026#34;8000:8000\u0026#34; deploy: resources: limits: memory: 10G # leaves ~14 GB for DB + other services embed: image: ghcr.io/huggingface/text-embeddings-inference:latest command: \u0026gt; --model-id phi3-mini-embedding-gguf --dtype auto volumes: - ./models:/models:ro ports: - \u0026#34;8100:8100\u0026#34; deploy: resources: limits: memory: 5G vector-db: image: qdrant/qdrant:latest ports: - \u0026#34;6333:6333\u0026#34; volumes: - ./qdrant_storage:/qdrant/storage deploy: resources: limits: memory: 6G api: build: ./api ports: - \u0026#34;8080:8080\u0026#34; depends_on: - llm - embed - vector-db deploy: resources: limits: memory: 2G Tip: If you run on a GPU with 8 GB VRAM, you can switch the llm service to vllm with --gpu-memory-utilization 0.9 and keep the same model size; the RAM footprint on the host drops dramatically.\nQuick “Which One to Pick?” Decision Tree # Situation Recommended Model You need the smallest RAM footprint (≤ 8 GB) and want a dedicated embedding head out‑of‑the‑box. Phi‑3‑mini (3.8B) You need strong multilingual (especially Chinese) support and want a single model for both generation and embeddings. Qwen‑1.5‑7B‑Chat You want a permissive licence and the best overall instruction‑following for a 7B model (with a mature ecosystem). Mistral‑7B‑Instruct You prefer a Google‑backed model with an official embedding checkpoint and good reasoning. Gemma‑2‑7B‑Instruct You already have a Meta‑centric stack or want to stay compatible with existing Llama‑2 pipelines (and can obtain a commercial licence if needed). Llama 2 7B‑Chat Summary of Strengths \u0026amp; Weaknesses # Model Strengths (Top 3) Weaknesses (Top 3) Llama 2 7B‑Chat • Proven instruction fine‑tuning.\n• Huge community tooling.\n• Good code \u0026amp; reasoning. • Commercial licence needed for closed‑source products.\n• Slightly larger RAM at 8‑bit.\n• No native embedding checkpoint (requires separate model). Mistral‑7B‑Instruct • Best open‑source instruction performance at 7B.\n• Apache 2.0 licence (no restrictions).\n• Fast inference on CPU/GPU. • No dedicated embedding model.\n• 32 k context may need extra RAM for very long prompts.\n• Slightly less “plug‑and‑play” for RAG. Phi‑3‑mini (3.8B) • Tiny RAM \u0026amp; compute footprint.\n• Built‑in embedding head.\n• MIT licence – fully commercial. • Lower generation quality for creative tasks.\n• English‑centric.\n• No vision component. Gemma‑2‑7B‑Instruct • Strong reasoning \u0026amp; multilingual.\n• Official embedding checkpoint.\n• Apache 2.0 licence. • Ecosystem still maturing (some serving tools lag behind).\n• Slightly larger RAM than Phi‑3‑mini.\n• Not as battle‑tested in production as Llama 2. Qwen‑1.5‑7B‑Chat • Excellent multilingual (incl. Chinese).\n• Embedding checkpoint available.\n• Apache 2.0 licence. • Documentation \u0026amp; community smaller (English).\n• 32 k context → higher RAM for long prompts.\n• Some serving frameworks still adding full support. Final Recommendations # Start with Phi‑3‑mini if you want the lightest setup and you only need English‑centric RAG + embeddings. It will comfortably run on a 16 GB RAM laptop or a small VPS.\nUpgrade to Gemma‑2‑7B‑Instruct or Mistral‑7B‑Instruct when you need better reasoning, code generation, or multilingual coverage while still staying under 24 GB RAM.\nChoose Llama 2 7B‑Chat if you already have pipelines built around Llama‑style tokenizers and you can obtain a commercial licence for production.\nPick Qwen‑1.5‑7B‑Chat if your corpus contains a lot of non‑English (especially Chinese) content and you want a single model that handles both generation and embeddings.\nAll five models can be quantised to 4‑bit GGUF, served via vLLM/llama‑cpp/TGI, and combined with FAISS/Qdrant + LangChain/LlamaIndex to deliver a full‑stack local LLM server that fits comfortably inside a 16‑24 GB RAM machine. Happy building! 🚀\n","date":null,"permalink":"https://ntwk.es/ca/posts/post_003/","section":"Articles del Blog Tecnològic","summary":"","title":"Local LLM Deployment on 16-24GB RAM"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/gcp/","section":"Tags","summary":"","title":"GCP"},{"content":"","date":null,"permalink":"https://ntwk.es/ca/tags/google-calendar/","section":"Tags","summary":"","title":"Google Calendar"},{"content":"Mòdul Calendari FileMaker # Un mòdul FileMaker auto-contingut que connecta la teva solució de base de dades amb Google Calendar Platform (GCP) i qualsevol aplicació de calendari compatible amb iCal / WebDav, incloent Microsoft 365 i Office 365. Dissenyat per integrar-se amb mínima fricció en desenvolupaments ERP, CRM o FileMaker personalitzats existents.\nNovetat — 1 de Març de 2026: hem llançat un servidor DAV local que s\u0026rsquo;integra nativament amb aquest mòdul, permetent a la teva empresa allotjar els seus propis serveis de calendari internament — sense dependència de núvol externa requerida. Estructura de Dades Principal #El mòdul inclou un conjunt complet de taules llestes per usar:\nTaula de comptes de servei — gestiona credencials de comptes de servei GCP usades per autenticació API Taula de calendaris — emmagatzema definicions de calendaris seguint l\u0026rsquo;estàndard GCP Taula de subscripcions — vincula comptes de servei a calendaris existents Taula d\u0026rsquo;esdeveniments — registres complets d\u0026rsquo;esdeveniments compatibles amb l\u0026rsquo;esquema d\u0026rsquo;esdeveniments de calendari GCP 10 camps d\u0026rsquo;usuari genèrics per esdeveniment — camps de lliure ús per vincular esdeveniments a registres en les teves pròpies taules d\u0026rsquo;aplicació Totes les taules de suport d\u0026rsquo;endpoints API estan pre-construïdes i llestes per a futures extensions sense canvis d\u0026rsquo;esquema.\nIntegració Google Cloud Platform #L\u0026rsquo;autenticació i les trucades API es gestionen completament dins de FileMaker usant un JWT generat nativament per l\u0026rsquo;aplicació — sense middleware extern requerit.\nAPIs de Google Calendar implementades:\nAPI Abast Autenticació Flux JWT OAuth 2.0 de compte de servei Calendars Lectura i edició limitada de calendaris primaris i secundaris CalendarList Subscriure comptes de servei a qualsevol calendari Events Creació, lectura, actualització i eliminació completa dins de privilegis assignats Els calendaris propietat de comptes de servei són compatibles però no es recomanen com a objectius primaris: no són accessibles públicament via enllaços iCal i no es poden compartir amb usuaris finals a través d\u0026rsquo;aplicacions de calendari estàndard.\nExclosos del mòdul base (disponibles com a complements separats): gestió de participants i invitacions, fitxers adjunts, recordatoris, alarmes i camps de reunions/conferències.\nConnectivitat iCal #Qualsevol aplicació de calendari que suporti el protocol iCal pot subscriure\u0026rsquo;s als calendaris gestionats per aquest mòdul a través del feed iCal natiu de GCP:\nmacOS / iOS — Calendar.app Windows — Outlook Calendar Android — Google Calendar Qualsevol altra aplicació compatible amb iCal L\u0026rsquo;accés de lectura/escriptura des d\u0026rsquo;aquestes aplicacions externes està controlat exclusivament per la configuració de privilegis a la consola de gestió GCP.\nVisualitzador de Calendari Web Interactiu #Una vista de calendari completament interactiva està incrustada directament al teu layout FileMaker usant un component WebViewer potenciat per les llibreries JavaScript de FullCalendar.io. Les dades es serveixen en viu a través del FileMaker Data API — el consum no compta contra les quotes de llicenciament de FileMaker.\nCapacitats del WebViewer:\nCàrrega de dades dinàmica — calendaris i esdeveniments il·limitats, filtrats per una cerca configurable de FileMaker Selecció, creació i eliminació d\u0026rsquo;esdeveniments Editor popup en línia per títol i descripció Arrossegar i deixar per reprogramar esdeveniments Redimensionar esdeveniments per canviar durada Alternar entre esdeveniments temporitzats i de dia complet Creació i edició d\u0026rsquo;esdeveniments multi-dia Zones de bloc de temps acolorides/reservades Tota la navegació UI i estils configurables via script FileMaker Vistes configurables: Agenda, Dia, Setmana, Mes, Multi-mes Operació Offline i Híbrida #El mòdul no depèn exclusivament de la connectivitat GCP. Pot operar en tres modes:\nSincronització en viu completa — els canvis a FileMaker s\u0026rsquo;envien a GCP en temps real Sincronització diferida — els canvis es posen en cua i s\u0026rsquo;envien quan la connectivitat està disponible Autònom / només local — totes les dades romanen a FileMaker sense dependència de GCP Notes d\u0026rsquo;Integració #El mòdul s\u0026rsquo;entrega com un arxiu FileMaker (.fmp12) llest per ser importat o referenciat com a font de dades externa. La infraestructura de taules pre-construïda significa que les futures extensions d\u0026rsquo;API no requereixen canvis estructurals a la teva solució existent.\nLa configuració del projecte GCP i el compte de servei estan incloses a l\u0026rsquo;entrega — la configuració inicial del núvol es gestiona com a part de la instal·lació del mòdul.\nCaptures de Pantalla # Secció tècnica detallada: La secció de captures de pantalla i demostració en viu està disponible a la versió en anglès. Totes les funcionalitats mostrades a les imatges i vídeos estan completament disponibles en aquesta versió del mòdul. Mòdul FMGCalendar — Preus 2026 # No hi ha botiga online. Aquest lloc no ven mòduls directament. Per a compres, pressupostos personalitzats, configuracions agrupades o sol·licituds especials, si us plau contacti\u0026rsquo;ns perquè puguem discutir termes, llicenciament i opcions d\u0026rsquo;implementació. Versió Bàsica #Aplicació de gestió de calendaris i esdeveniments, amb nombre il·limitat de calendaris i esdeveniments.\nVisualitzador WebViewer basat en el framework FullCalendar.io (edició bàsica), amb un conjunt complet d\u0026rsquo;opcions de configuració directament des de l\u0026rsquo;aplicació — configurable globalment, per usuari, o depenent del context de l\u0026rsquo;aplicació client. Els nous esdeveniments es poden crear des del propi mòdul de calendari (clic o clic+arrossegament), i els esdeveniments existents es poden editar mitjançant un popup contextual.\nEls calendaris i esdeveniments es poden filtrar per qualsevol criteri i rang de dates.\nEntrada de dades convencional via la base de dades.\nAccés a calendaris des de qualsevol aplicació de calendari compatible amb l\u0026rsquo;estàndard iCal (Google Calendar via navegador web, o aplicacions de calendari com Apple Calendar, iOS Calendar, Apple CarPlay, Apple Watch, Android Google Calendar, Windows Calendar, Outlook, Office 365, etc.).\nIntegració: fins a 10 camps de dades addicionals disponibles i públicament accessibles.\nRequisits del sistema:\nVersions de FileMaker \u0026gt; 20 (Mac o Windows) Plugin BaseElements 4.2 o posterior Funciona a FileMaker Pro o Server No disponible a plataformes iOS Preu Versió Bàsica 350 € Versió Bàsica + Integració Google Calendar #Inclou totes les característiques de la versió Bàsica més sincronització completa amb Google Cloud Platform, connectant a un nombre il·limitat de calendaris no públics (privats) configurats amb accés de lectura/escriptura per a un compte de servei.\nAPIs de gestió disponibles per a Calendars, CalendarList i Events (altres APIs disponibles a través de mòduls addicionals).\nAccés complet a les APIs de gestió de Colors, Settings i Channels, actuant com a APIs generals de control i configuració.\nAccés complet a l\u0026rsquo;API des de Scripts de FileMaker.\nRequisits del sistema: (igual que versió Bàsica)\nPreu Bàsica + Integració GC 950 € Requereix un compte d\u0026rsquo;usuari de Google Calendar i l\u0026rsquo;addició d\u0026rsquo;un Compte de Servei dedicat.\nMòdul Server Push (Webhooks Google Calendar) #Aplicació de servidor web que rep notificacions push (via webhooks) enviades per Google Cloud Platform per a un rang d\u0026rsquo;esdeveniments relacionats amb l\u0026rsquo;estat de calendaris, esdeveniments, participants, reunions o fitxers vinculats. Per a versions lliurades el 2026 els webhooks es construeixen sobre API ODATA\nInclou una interfície a l\u0026rsquo;API de subscripció de Google Calendar. Requereix accessibilitat a Internet (IP públic permanent, o IP dinàmica amb DNS dinàmic).\nPreu Mòdul webhooks 350 € Altres Mòduls Complementaris Disponibles # Mòdul de recordatoris / \u0026ldquo;alertes\u0026rdquo; + Subscriptors d\u0026rsquo;esdeveniments (gestió de recordatoris/alertes) Mòdul de conferències (gestió de reunions en línia) Mòdul de fitxers vinculats (compte Google Drive). Aquest mòdul està inclòs a la versió Bàsica i no requereix configuració addicional per a versions a partir del 2026. Cada mòdul complementari té un preu de 85 €, i no inclou implementació o configuració addicional de compte de Google* (Excepte el mòdul d\u0026rsquo;adjunts Google Drive).\nSuport d\u0026rsquo;Implementació #Suport addicional o instal·lació, configuració i qualsevol altra tasca de suport requerida per posar el mòdul en operació dins de l\u0026rsquo;entorn client objectiu.\nPreu Implementació client final 500 € No inclou treball de personalització en cap element del Mòdul Calendari o mòduls complementaris. Suport de Manteniment # Tarifa Paquet Mode 80 €/hora Paquet 5 hores remot 60 €/hora Paquet 30 hores remot 120 € una visita in situ — Visites in situ dins de l\u0026rsquo;àrea de Barcelona. Llicència (desenvolupador) #No hi ha llicències de distribució ni llicències de paquet de redistribució per a desenvolupadors. Els desenvolupadors que necessitin incorporar els mòduls en solucions verticals, desenvolupaments interns o implementacions per als seus propis clients directes rebran un descompte sobre els preus de llista basat en el nombre acumulat d\u0026rsquo;implementacions, de la següent manera:\nLlindar Descompte Fins a cinc (5) implementacions -25% de tots els preus Implementacions posteriors -35% de tots els preus Actualitzacions #Les actualitzacions principals tenen un preu del 50% del cost de la instal·lació existent.\nLes actualitzacions de manteniment són gratuïtes.\nSi una actualització requereix assistència o suport de manteniment, s\u0026rsquo;aplica el mateix percentatge sobre els preus de llista per a aquells elements.\nGarantia #Garantia funcional permanent i il·limitada en cas de defectes als mòduls que formen part de la implementació acordada. Aquesta garantia roman activa indefinidament, excepte en cas de qualsevol tipus de manipulació dels mòduls, o una actualització del programari FileMaker / FileMaker Server o del sistema operatiu en què el mòdul va ser originalment desplegat.\nExclusions # Autoria explícita de manuals d\u0026rsquo;aplicació fora de la documentació autònoma i serveis no detallats aquí. Formació específica. ","date":null,"permalink":"https://ntwk.es/ca/modules/calendar_module/","section":"Mòduls","summary":"Mòdul FileMaker auto-contingut que connecta la teva base de dades amb Google Calendar Platform i qualsevol aplicació de calendari iCal/WebDAV. Visualitzador web interactiu FullCalendar.io, calendaris i esdeveniments il·limitats, sincronització bidireccional i integració perfecta en solucions ERP, CRM o FileMaker personalitzades existents.","title":"Mòdul FM GCalendar"},{"content":"Els projectes més rellevants desenvolupats i desplegats durant els últims 20 anys. El nostre portafoli abasta sistemes empresarials, solucions de senyalització digital, tecnologia minorista i arquitectures de programari innovadores a tot Espanya, Europa i més enllà.\nProjectes Destacats #Feu clic en qualsevol projecte per obtenir més informació sobre el nostre treball, enfoc tècnic i impacte.\nSistemes Empresarials i Esportius # Centro de Alto Rendimiento (CAR) - OARC — Sistema de gestió de rendiment del centre atlètic d\u0026rsquo;elit d\u0026rsquo;Espanya (2007–2019) Corporación Roca - Sistema de Catàleg Corporatiu — Catàleg de productes internacional i senyalització digital (1998–2007) Retail i Pantalles Interactives # Dehner GmbH - Catàleg de Productes Interactiu — 140+ centres minoristes amb catàleg de pantalla tàctil (2014–2016) Desigual - Catàleg de Productes Interactiu — Experiència minorista de marca de moda (2011–2012) Migros-Gondelkopf - Pantalles d\u0026rsquo;Informació de Productes — 500+ terminals minoristes sincronitzats GLOBUS - Terminalls de Productes Sincronitzats — 500+ terminals d\u0026rsquo;hipermercat (2015) Senyalització Digital i Gestió de Continguts # Sport Förg GmbH - Senyalització Digital i Wayfinding — Navegació a la botiga i gestió de continguts (2013–2016) Echion Corporate Communication - CMS i Senyalització Digital — Plataforma SaaS multi-client (2013–2016) TMTFactory - Sistema de Gestió de Continguts DCBox — Agregació i distribució de continguts (2008–2012) NEO Advertising - Campanyes Digitals Dinàmiques — Campanyes basades en dades en temps real (2012) ANWR GROUP - Portal de Marketing — Gestió de continguts i llistes de reproducció (2013–2015) Tecnologia Avançada i Innovació # NEC Displays Europe - Integració LeafEngine — Senyalització digital basada en gestos (2013–2014) OneBox Ticketing - Sistema de Selecció de Seients — Venda d\u0026rsquo;entrades multiplataforma (2009–2010) Kendu POS - Sistema de Gestió Visual — Gestió de punts de venda internacionals (2009–2010) ","date":null,"permalink":"https://ntwk.es/ca/work/","section":"El nostre Treball al llarg dels anys","summary":"","title":"El nostre Treball al llarg dels anys"},{"content":"Codi Obert i Blocs de Construcció per a Desenvolupadors #Exploreu la nostra col·lecció de projectes de codi obert, mostres de codi i eines per a desenvolupadors. Creiem en compartir coneixement i contribuir a la comunitat de desenvolupadors.\nnBCN Software a GitHub\nProjectes Destacats # ODATA Client fm-odata-js # Client OData en un webviewer Client TypeScript sense dependències en temps d\u0026rsquo;execució per a l\u0026rsquo;API OData v4 de FileMaker Server. Es distribueix com un únic mòdul ES (~3 KB comprimit) llest per utilitzar en Web Viewers de FileMaker, navegadors moderns o Node 18+.\nLes característiques clau inclouen: un constructor de consultes fluid amb $select, $filter, $orderby, $top, $skip i $count; lectura de col·leccions i CRUD d\u0026rsquo;entitats individuals; autenticació Basic i Bearer amb reintent davant 401; suport per a AbortSignal i temps d\u0026rsquo;espera; un FMODataError normalitzat; i una API TypeScript completament tipada sense dependències en temps d\u0026rsquo;execució. Dissenyat per integrar-se en Web Viewers de FileMaker, navegadors i aplicacions Node.js.\nComponent Desplaçable (Swipeable Component) #Un component desplaçable modern i amigable amb el tacte per a aplicacions web. Aquest component proporciona navegació basada en gestos suaus i patrons d\u0026rsquo;interacció, perfecte per a interfícies mobile-first i aplicacions habilitades per a tacte.\nLes característiques clau inclouen: detecció de gestos tàctils responsiva, transicions d\u0026rsquo;animació suaus, llindars de desplaçament personalitzables, suport per a orientacions horitzontal i vertical, i implementació lleugera amb dependències mínimes. El component està dissenyat per millorar l\u0026rsquo;experiència de l\u0026rsquo;usuari en aplicacions web mòbils proporcionant interaccions de desplaçament intuïtives similars a les aplicacions mòbils natives.\nClipBroker # Aplicació FileMaker Clipbroker Aquest és un mòdul de FileMaker Pro per emmagatzemar i gestionar objectes del porta-retalls de FileMaker (Snippets), amb eines de conversió integrades per a contingut generat per IA. Serveix tant com a repositori de snippets per a components de FileMaker i com a convertidor de porta-retalls que permet una transferència fluida entre el format del porta-retalls de FileMaker i XML llegible per humans.\nLes característiques clau inclouen: emmagatzematge de components de FileMaker reutilitzables com scripts i funcions personalitzades, conversió de XML en format SaXML generat per IA en snippets de FileMaker utilitzables, i facilitació de l\u0026rsquo;intercanvi fàcil de biblioteques de codi entre equips. L\u0026rsquo;eina està dissenyada per facilitar fluxos de treball de desenvolupament assistits per IA on els desenvolupadors poden demanar a assistents d\u0026rsquo;IA que generin objectes de FileMaker en format XML, després enganxar-los i convertir-los directament en snippets utilitzables.\nServidors MCP de FileMaker Data API i ODATA # El servidor MCP FM-ODATA treballant amb Claude Introspecció completa i interacció amb solucions FileMaker a través d\u0026rsquo;agents d\u0026rsquo;IA. Permet que la IA entengui tota la vostra arquitectura de FileMaker i generi codi llest per a producció.\nServidor MCP de FileMaker Data API # Servidor MCP de FileMaker ODATA # Imatge Docker de FileMaker Server a Linux #Script Docker per construir una imatge de FileMaker Server 2025 a Ubuntu 24. Simplifica el desplegament i proves de FileMaker Server en entorns contenidoritzats. Una mica més que un ajust al script proporcionat per Claris.\nFragments de Codi i Gists #Fragments de codi útils i exemples per a desenvolupadors que treballen amb FileMaker, integracions i tecnologies relacionades estan disponibles als nostres GitHub Gists.\nGists de nBCN Software\nSuport #Cada repositori té el seu propi procés de suport. Per a preguntes, problemes o sol·licituds de característiques:\nGitHub Issues — Informeu d\u0026rsquo;errors i sol·liciteu característiques en repositoris individuals Email — tecnic@ntwk.es Manteniu-vos actualitzats — Seguiu els nostres repositoris de GitHub per rebre notificacions sobre nous llançaments i actualitzacions.\n","date":null,"permalink":"https://ntwk.es/ca/resources/","section":"Recursos","summary":"","title":"Recursos"}]