[{"data":1,"prerenderedAt":2122},["ShallowReactive",2],{"blog-en-/en/blog/on-premise-ai-solutions-with-ollama":3},{"id":4,"title":5,"body":6,"description":2107,"extension":2108,"meta":2109,"navigation":296,"path":2118,"seo":2119,"stem":2120,"__hash__":2121},"en_blog/en/blog/on-premise-ai-solutions-with-ollama.md","On-Premise AI Solutions with Ollama: Factory-Internal Predictive Maintenance",{"type":7,"value":8,"toc":2077},"minimark",[9,14,43,60,64,69,74,107,111,230,234,245,249,253,402,406,434,438,442,451,464,468,473,986,991,1069,1073,1076,1082,1086,1091,1534,1538,1620,1624,1628,1633,1647,1652,1708,1712,1915,1919,1923,1928,1993,1999,2003,2012,2032,2045,2049,2073],[10,11,13],"h2",{"id":12},"introduction","Introduction",[15,16,17,18,22,23,26,27,30,31,34,35,38,39,42],"p",{},"In industrial facilities, ",[19,20,21],"strong",{},"data privacy"," and ",[19,24,25],{},"real-time decision making"," are critical requirements. While cloud-based AI services like ",[19,28,29],{},"AWS Bedrock"," or ",[19,32,33],{},"OpenAI"," offer powerful capabilities, they require sensitive production data to leave the facility. ",[19,36,37],{},"Ollama"," addresses this issue by enabling ",[19,40,41],{},"local Large Language Model (LLM)"," deployment.",[15,44,45,46,22,51,55,56,59],{},"In this article, we examine how to implement AI-powered predictive maintenance applications using Ollama with our ",[47,48,50],"a",{"href":49},"/en/products/zma-data-acquisition","ZMA Data Acquisition",[47,52,54],{"href":53},"/en/products/gdt-digital-transmitter","GDT Digital Transmitter"," devices, ",[19,57,58],{},"without any cloud connection",".",[10,61,63],{"id":62},"what-is-ollama","What is Ollama?",[15,65,66,68],{},[19,67,37],{}," is an open-source application that enables local deployment of large language models like Llama, Mistral, Phi.",[70,71,73],"h3",{"id":72},"key-features","Key Features",[15,75,76,77,80,81,84,85,88,89,84,91,94,95,84,97,100,101,84,103,106],{},"✅ ",[19,78,79],{},"Fully Local:"," All data stays within facility",[82,83],"br",{},"\n✅ ",[19,86,87],{},"No Internet Required:"," Complete offline operation",[82,90],{},[19,92,93],{},"Open Source Models:"," Llama 3, Mistral 7B, Phi-3",[82,96],{},[19,98,99],{},"Easy API:"," Compatible with OpenAI API",[82,102],{},[19,104,105],{},"Low Cost:"," No per-token API fees",[70,108,110],{"id":109},"cloud-ai-vs-ollama-comparison","Cloud AI vs Ollama Comparison",[112,113,114,132],"table",{},[115,116,117],"thead",{},[118,119,120,124,126,129],"tr",{},[121,122,123],"th",{},"Feature",[121,125,29],{},[121,127,128],{},"OpenAI GPT-4",[121,130,131],{},"Ollama (Local)",[133,134,135,151,166,182,198,214],"tbody",{},[118,136,137,143,146,148],{},[138,139,140],"td",{},[19,141,142],{},"Data Privacy",[138,144,145],{},"Data leaves facility",[138,147,145],{},[138,149,150],{},"Fully local",[118,152,153,158,161,163],{},[138,154,155],{},[19,156,157],{},"Internet Dependency",[138,159,160],{},"Required",[138,162,160],{},[138,164,165],{},"Not required",[118,167,168,173,176,179],{},[138,169,170],{},[19,171,172],{},"Latency",[138,174,175],{},"200-500ms",[138,177,178],{},"300-800ms",[138,180,181],{},"50-200ms",[118,183,184,189,192,195],{},[138,185,186],{},[19,187,188],{},"Cost",[138,190,191],{},"$0.00025-0.01/1K token",[138,193,194],{},"$0.01-0.06/1K token",[138,196,197],{},"Hardware only",[118,199,200,205,208,211],{},[138,201,202],{},[19,203,204],{},"Customization",[138,206,207],{},"Limited",[138,209,210],{},"No",[138,212,213],{},"Full control",[118,215,216,221,224,227],{},[138,217,218],{},[19,219,220],{},"Model Size",[138,222,223],{},"Large (100B+)",[138,225,226],{},"Very large (1.7T)",[138,228,229],{},"Small-Medium (7B-70B)",[10,231,233],{"id":232},"system-architecture","System Architecture",[235,236,241],"pre",{"className":237,"code":239,"language":240},[238],"language-text","┌──────────────────────────────────────────────────┐\n│              Factory (Fully Offline)             │\n│                                                  │\n│  ┌─────────┐    Modbus TCP    ┌──────────────┐  │\n│  │ ZMA-4   │◄─────────────────►│              │  │\n│  │ Devices │                   │  Linux PC    │  │\n│  └─────────┘                   │  (AI Server) │  │\n│                                │              │  │\n│  ┌─────────┐    Modbus TCP    │ - Ollama     │  │\n│  │ GDT     │◄─────────────────►│ - Python     │  │\n│  │ Trans.  │                   │ - PostgreSQL │  │\n│  └─────────┘                   │              │  │\n│                                │ Models:      │  │\n│                                │ • Llama 3.2  │  │\n│                                │ • Mistral 7B │  │\n│                                │ • Phi-3      │  │\n│                                └──────────────┘  │\n│                                                  │\n└──────────────────────────────────────────────────┘\n","text",[242,243,239],"code",{"__ignoreMap":244},"",[10,246,248],{"id":247},"ollama-installation-and-setup","Ollama Installation and Setup",[70,250,252],{"id":251},"_1-server-installation-ubuntu-2204","1. Server Installation (Ubuntu 22.04)",[235,254,258],{"className":255,"code":256,"language":257,"meta":244,"style":244},"language-bash shiki shiki-themes github-light github-dark","# Install Ollama\ncurl -fsSL https://ollama.com/install.sh | sh\n\n# Start Ollama service\nsudo systemctl start ollama\nsudo systemctl enable ollama\n\n# Download models\nollama pull llama3.2:3b      # 3B parameter model (~2GB)\nollama pull mistral:7b       # 7B parameter model (~4.1GB)\nollama pull phi3:medium      # 14B parameter model (~7.9GB)\n\n# Verify installation\nollama list\n","bash",[242,259,260,269,291,298,304,319,331,336,342,357,370,383,388,394],{"__ignoreMap":244},[261,262,265],"span",{"class":263,"line":264},"line",1,[261,266,268],{"class":267},"sJ8bj","# Install Ollama\n",[261,270,272,276,280,284,288],{"class":263,"line":271},2,[261,273,275],{"class":274},"sScJk","curl",[261,277,279],{"class":278},"sj4cs"," -fsSL",[261,281,283],{"class":282},"sZZnC"," https://ollama.com/install.sh",[261,285,287],{"class":286},"szBVR"," |",[261,289,290],{"class":274}," sh\n",[261,292,294],{"class":263,"line":293},3,[261,295,297],{"emptyLinePlaceholder":296},true,"\n",[261,299,301],{"class":263,"line":300},4,[261,302,303],{"class":267},"# Start Ollama service\n",[261,305,307,310,313,316],{"class":263,"line":306},5,[261,308,309],{"class":274},"sudo",[261,311,312],{"class":282}," systemctl",[261,314,315],{"class":282}," start",[261,317,318],{"class":282}," ollama\n",[261,320,322,324,326,329],{"class":263,"line":321},6,[261,323,309],{"class":274},[261,325,312],{"class":282},[261,327,328],{"class":282}," enable",[261,330,318],{"class":282},[261,332,334],{"class":263,"line":333},7,[261,335,297],{"emptyLinePlaceholder":296},[261,337,339],{"class":263,"line":338},8,[261,340,341],{"class":267},"# Download models\n",[261,343,345,348,351,354],{"class":263,"line":344},9,[261,346,347],{"class":274},"ollama",[261,349,350],{"class":282}," pull",[261,352,353],{"class":282}," llama3.2:3b",[261,355,356],{"class":267},"      # 3B parameter model (~2GB)\n",[261,358,360,362,364,367],{"class":263,"line":359},10,[261,361,347],{"class":274},[261,363,350],{"class":282},[261,365,366],{"class":282}," mistral:7b",[261,368,369],{"class":267},"       # 7B parameter model (~4.1GB)\n",[261,371,373,375,377,380],{"class":263,"line":372},11,[261,374,347],{"class":274},[261,376,350],{"class":282},[261,378,379],{"class":282}," phi3:medium",[261,381,382],{"class":267},"      # 14B parameter model (~7.9GB)\n",[261,384,386],{"class":263,"line":385},12,[261,387,297],{"emptyLinePlaceholder":296},[261,389,391],{"class":263,"line":390},13,[261,392,393],{"class":267},"# Verify installation\n",[261,395,397,399],{"class":263,"line":396},14,[261,398,347],{"class":274},[261,400,401],{"class":282}," list\n",[70,403,405],{"id":404},"_2-python-integration","2. Python Integration",[235,407,409],{"className":255,"code":408,"language":257,"meta":244,"style":244},"pip install ollama requests pymodbus psycopg2-binary pandas\n",[242,410,411],{"__ignoreMap":244},[261,412,413,416,419,422,425,428,431],{"class":263,"line":264},[261,414,415],{"class":274},"pip",[261,417,418],{"class":282}," install",[261,420,421],{"class":282}," ollama",[261,423,424],{"class":282}," requests",[261,426,427],{"class":282}," pymodbus",[261,429,430],{"class":282}," psycopg2-binary",[261,432,433],{"class":282}," pandas\n",[10,435,437],{"id":436},"application-1-anomaly-detection-from-loadcell-data","Application 1: Anomaly Detection from Loadcell Data",[70,439,441],{"id":440},"scenario","Scenario",[15,443,444,446,447,450],{},[47,445,54],{"href":53}," reads weight from 4 loadcells on a tank. ",[19,448,449],{},"Imbalanced load"," (one loadcell reading much higher/lower) may indicate:",[452,453,454,458,461],"ul",{},[455,456,457],"li",{},"Tank tilt",[455,459,460],{},"Loadcell failure",[455,462,463],{},"Foundation problem",[70,465,467],{"id":466},"ai-powered-detection","AI-Powered Detection",[15,469,470],{},[19,471,472],{},"anomaly_detector.py",[235,474,478],{"className":475,"code":476,"language":477,"meta":244,"style":244},"language-python shiki shiki-themes github-light github-dark","#!/usr/bin/env python3\n\nimport ollama\nimport json\nfrom pymodbus.client.sync import ModbusTcpClient\n\nclass LoadcellAnomalyDetector:\n    def __init__(self):\n        self.gdt_client = ModbusTcpClient('192.168.1.100', port=502)\n        self.gdt_client.connect()\n\n        # Use lightweight model (3B)\n        self.model = \"llama3.2:3b\"\n\n    def read_loadcells(self):\n        \"\"\"Read 4 loadcell values from GDT\"\"\"\n        result = self.gdt_client.read_holding_registers(10, 8, unit=1)\n\n        if not result.isError():\n            lc1 = self._to_float(result.registers[0:2])\n            lc2 = self._to_float(result.registers[2:4])\n            lc3 = self._to_float(result.registers[4:6])\n            lc4 = self._to_float(result.registers[6:8])\n\n            return {\n                \"lc1\": round(lc1, 3),\n                \"lc2\": round(lc2, 3),\n                \"lc3\": round(lc3, 3),\n                \"lc4\": round(lc4, 3),\n                \"total\": round(lc1 + lc2 + lc3 + lc4, 3)\n            }\n        return None\n\n    def analyze_with_ai(self, data):\n        \"\"\"Analyze loadcell values with Ollama\"\"\"\n        prompt = f\"\"\"\nYou are an industrial automation expert. Analyze the following loadcell readings:\n\nLoadcell 1 (Front-Left):  {data['lc1']} mV/V\nLoadcell 2 (Front-Right): {data['lc2']} mV/V\nLoadcell 3 (Rear-Left):   {data['lc3']} mV/V\nLoadcell 4 (Rear-Right):  {data['lc4']} mV/V\nTotal Weight: {data['total']} mV/V\n\nNormal state: All 4 loadcells should read similar values (±5% tolerance).\n\nTask: Detect any anomalies and provide:\n1. Is there an anomaly? (Yes/No)\n2. If yes, which loadcell?\n3. Probable cause\n4. Recommended action\n\nRespond in JSON format.\n\"\"\"\n\n        response = ollama.generate(\n            model=self.model,\n            prompt=prompt,\n            format='json'  # Force JSON output\n        )\n\n        result = json.loads(response['response'])\n        return result\n\n    def run(self):\n        \"\"\"Main monitoring loop\"\"\"\n        print(f\"🤖 AI Anomaly Detector started (Model: {self.model})\")\n\n        while True:\n            data = self.read_loadcells()\n\n            if data:\n                print(f\"\\n📊 Loadcells: {data}\")\n\n                # AI analysis\n                analysis = self.analyze_with_ai(data)\n\n                if analysis.get('anomaly') == 'Yes':\n                    print(f\"⚠️  ANOMALY DETECTED!\")\n                    print(f\"   Problem: {analysis.get('problem')}\")\n                    print(f\"   Cause: {analysis.get('probable_cause')}\")\n                    print(f\"   Action: {analysis.get('recommended_action')}\")\n                else:\n                    print(\"✓ Normal operation\")\n\n            time.sleep(10)  # Check every 10 seconds\n\nif __name__ == \"__main__\":\n    detector = LoadcellAnomalyDetector()\n    detector.run()\n","python",[242,479,480,485,489,494,499,504,508,513,518,523,528,532,537,542,546,552,558,564,569,575,581,587,593,599,604,610,616,622,628,634,640,646,652,657,663,669,675,681,686,692,698,704,710,716,721,727,732,738,744,750,756,762,767,773,779,784,790,796,802,808,814,819,825,831,836,842,848,854,859,865,871,876,882,888,893,899,905,910,916,922,928,934,940,946,952,957,963,968,974,980],{"__ignoreMap":244},[261,481,482],{"class":263,"line":264},[261,483,484],{},"#!/usr/bin/env python3\n",[261,486,487],{"class":263,"line":271},[261,488,297],{"emptyLinePlaceholder":296},[261,490,491],{"class":263,"line":293},[261,492,493],{},"import ollama\n",[261,495,496],{"class":263,"line":300},[261,497,498],{},"import json\n",[261,500,501],{"class":263,"line":306},[261,502,503],{},"from pymodbus.client.sync import ModbusTcpClient\n",[261,505,506],{"class":263,"line":321},[261,507,297],{"emptyLinePlaceholder":296},[261,509,510],{"class":263,"line":333},[261,511,512],{},"class LoadcellAnomalyDetector:\n",[261,514,515],{"class":263,"line":338},[261,516,517],{},"    def __init__(self):\n",[261,519,520],{"class":263,"line":344},[261,521,522],{},"        self.gdt_client = ModbusTcpClient('192.168.1.100', port=502)\n",[261,524,525],{"class":263,"line":359},[261,526,527],{},"        self.gdt_client.connect()\n",[261,529,530],{"class":263,"line":372},[261,531,297],{"emptyLinePlaceholder":296},[261,533,534],{"class":263,"line":385},[261,535,536],{},"        # Use lightweight model (3B)\n",[261,538,539],{"class":263,"line":390},[261,540,541],{},"        self.model = \"llama3.2:3b\"\n",[261,543,544],{"class":263,"line":396},[261,545,297],{"emptyLinePlaceholder":296},[261,547,549],{"class":263,"line":548},15,[261,550,551],{},"    def read_loadcells(self):\n",[261,553,555],{"class":263,"line":554},16,[261,556,557],{},"        \"\"\"Read 4 loadcell values from GDT\"\"\"\n",[261,559,561],{"class":263,"line":560},17,[261,562,563],{},"        result = self.gdt_client.read_holding_registers(10, 8, unit=1)\n",[261,565,567],{"class":263,"line":566},18,[261,568,297],{"emptyLinePlaceholder":296},[261,570,572],{"class":263,"line":571},19,[261,573,574],{},"        if not result.isError():\n",[261,576,578],{"class":263,"line":577},20,[261,579,580],{},"            lc1 = self._to_float(result.registers[0:2])\n",[261,582,584],{"class":263,"line":583},21,[261,585,586],{},"            lc2 = self._to_float(result.registers[2:4])\n",[261,588,590],{"class":263,"line":589},22,[261,591,592],{},"            lc3 = self._to_float(result.registers[4:6])\n",[261,594,596],{"class":263,"line":595},23,[261,597,598],{},"            lc4 = self._to_float(result.registers[6:8])\n",[261,600,602],{"class":263,"line":601},24,[261,603,297],{"emptyLinePlaceholder":296},[261,605,607],{"class":263,"line":606},25,[261,608,609],{},"            return {\n",[261,611,613],{"class":263,"line":612},26,[261,614,615],{},"                \"lc1\": round(lc1, 3),\n",[261,617,619],{"class":263,"line":618},27,[261,620,621],{},"                \"lc2\": round(lc2, 3),\n",[261,623,625],{"class":263,"line":624},28,[261,626,627],{},"                \"lc3\": round(lc3, 3),\n",[261,629,631],{"class":263,"line":630},29,[261,632,633],{},"                \"lc4\": round(lc4, 3),\n",[261,635,637],{"class":263,"line":636},30,[261,638,639],{},"                \"total\": round(lc1 + lc2 + lc3 + lc4, 3)\n",[261,641,643],{"class":263,"line":642},31,[261,644,645],{},"            }\n",[261,647,649],{"class":263,"line":648},32,[261,650,651],{},"        return None\n",[261,653,655],{"class":263,"line":654},33,[261,656,297],{"emptyLinePlaceholder":296},[261,658,660],{"class":263,"line":659},34,[261,661,662],{},"    def analyze_with_ai(self, data):\n",[261,664,666],{"class":263,"line":665},35,[261,667,668],{},"        \"\"\"Analyze loadcell values with Ollama\"\"\"\n",[261,670,672],{"class":263,"line":671},36,[261,673,674],{},"        prompt = f\"\"\"\n",[261,676,678],{"class":263,"line":677},37,[261,679,680],{},"You are an industrial automation expert. Analyze the following loadcell readings:\n",[261,682,684],{"class":263,"line":683},38,[261,685,297],{"emptyLinePlaceholder":296},[261,687,689],{"class":263,"line":688},39,[261,690,691],{},"Loadcell 1 (Front-Left):  {data['lc1']} mV/V\n",[261,693,695],{"class":263,"line":694},40,[261,696,697],{},"Loadcell 2 (Front-Right): {data['lc2']} mV/V\n",[261,699,701],{"class":263,"line":700},41,[261,702,703],{},"Loadcell 3 (Rear-Left):   {data['lc3']} mV/V\n",[261,705,707],{"class":263,"line":706},42,[261,708,709],{},"Loadcell 4 (Rear-Right):  {data['lc4']} mV/V\n",[261,711,713],{"class":263,"line":712},43,[261,714,715],{},"Total Weight: {data['total']} mV/V\n",[261,717,719],{"class":263,"line":718},44,[261,720,297],{"emptyLinePlaceholder":296},[261,722,724],{"class":263,"line":723},45,[261,725,726],{},"Normal state: All 4 loadcells should read similar values (±5% tolerance).\n",[261,728,730],{"class":263,"line":729},46,[261,731,297],{"emptyLinePlaceholder":296},[261,733,735],{"class":263,"line":734},47,[261,736,737],{},"Task: Detect any anomalies and provide:\n",[261,739,741],{"class":263,"line":740},48,[261,742,743],{},"1. Is there an anomaly? (Yes/No)\n",[261,745,747],{"class":263,"line":746},49,[261,748,749],{},"2. If yes, which loadcell?\n",[261,751,753],{"class":263,"line":752},50,[261,754,755],{},"3. Probable cause\n",[261,757,759],{"class":263,"line":758},51,[261,760,761],{},"4. Recommended action\n",[261,763,765],{"class":263,"line":764},52,[261,766,297],{"emptyLinePlaceholder":296},[261,768,770],{"class":263,"line":769},53,[261,771,772],{},"Respond in JSON format.\n",[261,774,776],{"class":263,"line":775},54,[261,777,778],{},"\"\"\"\n",[261,780,782],{"class":263,"line":781},55,[261,783,297],{"emptyLinePlaceholder":296},[261,785,787],{"class":263,"line":786},56,[261,788,789],{},"        response = ollama.generate(\n",[261,791,793],{"class":263,"line":792},57,[261,794,795],{},"            model=self.model,\n",[261,797,799],{"class":263,"line":798},58,[261,800,801],{},"            prompt=prompt,\n",[261,803,805],{"class":263,"line":804},59,[261,806,807],{},"            format='json'  # Force JSON output\n",[261,809,811],{"class":263,"line":810},60,[261,812,813],{},"        )\n",[261,815,817],{"class":263,"line":816},61,[261,818,297],{"emptyLinePlaceholder":296},[261,820,822],{"class":263,"line":821},62,[261,823,824],{},"        result = json.loads(response['response'])\n",[261,826,828],{"class":263,"line":827},63,[261,829,830],{},"        return result\n",[261,832,834],{"class":263,"line":833},64,[261,835,297],{"emptyLinePlaceholder":296},[261,837,839],{"class":263,"line":838},65,[261,840,841],{},"    def run(self):\n",[261,843,845],{"class":263,"line":844},66,[261,846,847],{},"        \"\"\"Main monitoring loop\"\"\"\n",[261,849,851],{"class":263,"line":850},67,[261,852,853],{},"        print(f\"🤖 AI Anomaly Detector started (Model: {self.model})\")\n",[261,855,857],{"class":263,"line":856},68,[261,858,297],{"emptyLinePlaceholder":296},[261,860,862],{"class":263,"line":861},69,[261,863,864],{},"        while True:\n",[261,866,868],{"class":263,"line":867},70,[261,869,870],{},"            data = self.read_loadcells()\n",[261,872,874],{"class":263,"line":873},71,[261,875,297],{"emptyLinePlaceholder":296},[261,877,879],{"class":263,"line":878},72,[261,880,881],{},"            if data:\n",[261,883,885],{"class":263,"line":884},73,[261,886,887],{},"                print(f\"\\n📊 Loadcells: {data}\")\n",[261,889,891],{"class":263,"line":890},74,[261,892,297],{"emptyLinePlaceholder":296},[261,894,896],{"class":263,"line":895},75,[261,897,898],{},"                # AI analysis\n",[261,900,902],{"class":263,"line":901},76,[261,903,904],{},"                analysis = self.analyze_with_ai(data)\n",[261,906,908],{"class":263,"line":907},77,[261,909,297],{"emptyLinePlaceholder":296},[261,911,913],{"class":263,"line":912},78,[261,914,915],{},"                if analysis.get('anomaly') == 'Yes':\n",[261,917,919],{"class":263,"line":918},79,[261,920,921],{},"                    print(f\"⚠️  ANOMALY DETECTED!\")\n",[261,923,925],{"class":263,"line":924},80,[261,926,927],{},"                    print(f\"   Problem: {analysis.get('problem')}\")\n",[261,929,931],{"class":263,"line":930},81,[261,932,933],{},"                    print(f\"   Cause: {analysis.get('probable_cause')}\")\n",[261,935,937],{"class":263,"line":936},82,[261,938,939],{},"                    print(f\"   Action: {analysis.get('recommended_action')}\")\n",[261,941,943],{"class":263,"line":942},83,[261,944,945],{},"                else:\n",[261,947,949],{"class":263,"line":948},84,[261,950,951],{},"                    print(\"✓ Normal operation\")\n",[261,953,955],{"class":263,"line":954},85,[261,956,297],{"emptyLinePlaceholder":296},[261,958,960],{"class":263,"line":959},86,[261,961,962],{},"            time.sleep(10)  # Check every 10 seconds\n",[261,964,966],{"class":263,"line":965},87,[261,967,297],{"emptyLinePlaceholder":296},[261,969,971],{"class":263,"line":970},88,[261,972,973],{},"if __name__ == \"__main__\":\n",[261,975,977],{"class":263,"line":976},89,[261,978,979],{},"    detector = LoadcellAnomalyDetector()\n",[261,981,983],{"class":263,"line":982},90,[261,984,985],{},"    detector.run()\n",[15,987,988],{},[19,989,990],{},"Example Output:",[235,992,996],{"className":993,"code":994,"language":995,"meta":244,"style":244},"language-json shiki shiki-themes github-light github-dark","{\n  \"anomaly\": \"Yes\",\n  \"problem\": \"Loadcell 3 reading is 15% lower than others\",\n  \"probable_cause\": \"Possible loadcell drift or loose connection\",\n  \"recommended_action\": \"Check Loadcell 3 wiring and recalibrate if necessary\",\n  \"severity\": \"Medium\"\n}\n","json",[242,997,998,1004,1018,1030,1042,1054,1064],{"__ignoreMap":244},[261,999,1000],{"class":263,"line":264},[261,1001,1003],{"class":1002},"sVt8B","{\n",[261,1005,1006,1009,1012,1015],{"class":263,"line":271},[261,1007,1008],{"class":278},"  \"anomaly\"",[261,1010,1011],{"class":1002},": ",[261,1013,1014],{"class":282},"\"Yes\"",[261,1016,1017],{"class":1002},",\n",[261,1019,1020,1023,1025,1028],{"class":263,"line":293},[261,1021,1022],{"class":278},"  \"problem\"",[261,1024,1011],{"class":1002},[261,1026,1027],{"class":282},"\"Loadcell 3 reading is 15% lower than others\"",[261,1029,1017],{"class":1002},[261,1031,1032,1035,1037,1040],{"class":263,"line":300},[261,1033,1034],{"class":278},"  \"probable_cause\"",[261,1036,1011],{"class":1002},[261,1038,1039],{"class":282},"\"Possible loadcell drift or loose connection\"",[261,1041,1017],{"class":1002},[261,1043,1044,1047,1049,1052],{"class":263,"line":306},[261,1045,1046],{"class":278},"  \"recommended_action\"",[261,1048,1011],{"class":1002},[261,1050,1051],{"class":282},"\"Check Loadcell 3 wiring and recalibrate if necessary\"",[261,1053,1017],{"class":1002},[261,1055,1056,1059,1061],{"class":263,"line":321},[261,1057,1058],{"class":278},"  \"severity\"",[261,1060,1011],{"class":1002},[261,1062,1063],{"class":282},"\"Medium\"\n",[261,1065,1066],{"class":263,"line":333},[261,1067,1068],{"class":1002},"}\n",[10,1070,1072],{"id":1071},"application-2-predictive-maintenance-from-vibration-data","Application 2: Predictive Maintenance from Vibration Data",[70,1074,441],{"id":1075},"scenario-1",[15,1077,1078,1081],{},[47,1079,1080],{"href":49},"ZMA-4"," collects vibration data from motor via accelerometer (4-20mA). Predict motor failure by analyzing data with AI.",[70,1083,1085],{"id":1084},"feature-extraction-ai-analysis","Feature Extraction + AI Analysis",[15,1087,1088],{},[19,1089,1090],{},"vibration_monitor.py",[235,1092,1094],{"className":475,"code":1093,"language":477,"meta":244,"style":244},"import numpy as np\nimport pandas as pd\nfrom scipy import signal\nfrom pymodbus.client.sync import ModbusTcpClient\nimport ollama\n\nclass VibrationAnalyzer:\n    def __init__(self):\n        self.zma_client = ModbusTcpClient('192.168.1.50', port=502)\n        self.zma_client.connect()\n        self.model = \"mistral:7b\"\n\n    def read_vibration_data(self, samples=1000):\n        \"\"\"Read 1000 samples from ZMA (1kHz sampling)\"\"\"\n        data = []\n        for _ in range(samples):\n            result = self.zma_client.read_holding_registers(0, 2, unit=1)\n            value = self._to_float(result.registers)\n            data.append(value)\n            time.sleep(0.001)  # 1ms = 1kHz\n\n        return np.array(data)\n\n    def extract_features(self, vibration_data):\n        \"\"\"Extract frequency domain features\"\"\"\n        # FFT\n        fft = np.fft.fft(vibration_data)\n        freqs = np.fft.fftfreq(len(vibration_data), d=0.001)\n\n        # Peak frequencies\n        peaks, _ = signal.find_peaks(np.abs(fft), height=100)\n        peak_freqs = freqs[peaks]\n\n        # Statistical features\n        features = {\n            \"rms\": np.sqrt(np.mean(vibration_data**2)),\n            \"peak\": np.max(np.abs(vibration_data)),\n            \"crest_factor\": np.max(np.abs(vibration_data)) / np.sqrt(np.mean(vibration_data**2)),\n            \"dominant_freq\": peak_freqs[0] if len(peak_freqs) > 0 else 0,\n            \"spectral_energy\": np.sum(np.abs(fft)**2)\n        }\n\n        return features\n\n    def predict_with_ai(self, features):\n        \"\"\"Predictive maintenance analysis with AI\"\"\"\n        prompt = f\"\"\"\nYou are a mechanical engineer expert in predictive maintenance. Analyze the following vibration data from an industrial motor:\n\nRMS Vibration: {features['rms']:.3f} m/s²\nPeak Vibration: {features['peak']:.3f} m/s²\nCrest Factor: {features['crest_factor']:.2f}\nDominant Frequency: {features['dominant_freq']:.1f} Hz\nSpectral Energy: {features['spectral_energy']:.2e}\n\nReference values:\n- Normal RMS: 0.5-2.0 m/s²\n- Warning RMS: 2.0-5.0 m/s²\n- Critical RMS: >5.0 m/s²\n- Normal Crest Factor: 3-4\n- Motor rotation: 1500 RPM (25 Hz)\n\nTask: Provide predictive maintenance assessment:\n1. Motor condition (Normal/Warning/Critical)\n2. Probable fault type (if any)\n3. Estimated time to failure (days)\n4. Recommended action\n\nRespond in JSON format.\n\"\"\"\n\n        response = ollama.generate(\n            model=self.model,\n            prompt=prompt,\n            format='json'\n        )\n\n        return json.loads(response['response'])\n\nif __name__ == \"__main__\":\n    analyzer = VibrationAnalyzer()\n\n    # Read vibration data\n    vibration = analyzer.read_vibration_data(1000)\n\n    # Extract features\n    features = analyzer.extract_features(vibration)\n    print(f\"📊 Features: {features}\")\n\n    # AI prediction\n    prediction = analyzer.predict_with_ai(features)\n    print(f\"\\n🔮 AI Prediction:\")\n    print(json.dumps(prediction, indent=2))\n",[242,1095,1096,1101,1106,1111,1115,1119,1123,1128,1132,1137,1142,1147,1151,1156,1161,1166,1171,1176,1181,1186,1191,1195,1200,1204,1209,1214,1219,1224,1229,1233,1238,1243,1248,1252,1257,1262,1267,1272,1277,1282,1287,1292,1296,1301,1305,1310,1315,1319,1324,1328,1333,1338,1343,1348,1353,1357,1362,1367,1372,1377,1382,1387,1391,1396,1401,1406,1411,1415,1419,1423,1427,1431,1435,1439,1443,1448,1452,1456,1461,1465,1469,1474,1478,1483,1488,1492,1497,1502,1507,1511,1516,1522,1528],{"__ignoreMap":244},[261,1097,1098],{"class":263,"line":264},[261,1099,1100],{},"import numpy as np\n",[261,1102,1103],{"class":263,"line":271},[261,1104,1105],{},"import pandas as pd\n",[261,1107,1108],{"class":263,"line":293},[261,1109,1110],{},"from scipy import signal\n",[261,1112,1113],{"class":263,"line":300},[261,1114,503],{},[261,1116,1117],{"class":263,"line":306},[261,1118,493],{},[261,1120,1121],{"class":263,"line":321},[261,1122,297],{"emptyLinePlaceholder":296},[261,1124,1125],{"class":263,"line":333},[261,1126,1127],{},"class VibrationAnalyzer:\n",[261,1129,1130],{"class":263,"line":338},[261,1131,517],{},[261,1133,1134],{"class":263,"line":344},[261,1135,1136],{},"        self.zma_client = ModbusTcpClient('192.168.1.50', port=502)\n",[261,1138,1139],{"class":263,"line":359},[261,1140,1141],{},"        self.zma_client.connect()\n",[261,1143,1144],{"class":263,"line":372},[261,1145,1146],{},"        self.model = \"mistral:7b\"\n",[261,1148,1149],{"class":263,"line":385},[261,1150,297],{"emptyLinePlaceholder":296},[261,1152,1153],{"class":263,"line":390},[261,1154,1155],{},"    def read_vibration_data(self, samples=1000):\n",[261,1157,1158],{"class":263,"line":396},[261,1159,1160],{},"        \"\"\"Read 1000 samples from ZMA (1kHz sampling)\"\"\"\n",[261,1162,1163],{"class":263,"line":548},[261,1164,1165],{},"        data = []\n",[261,1167,1168],{"class":263,"line":554},[261,1169,1170],{},"        for _ in range(samples):\n",[261,1172,1173],{"class":263,"line":560},[261,1174,1175],{},"            result = self.zma_client.read_holding_registers(0, 2, unit=1)\n",[261,1177,1178],{"class":263,"line":566},[261,1179,1180],{},"            value = self._to_float(result.registers)\n",[261,1182,1183],{"class":263,"line":571},[261,1184,1185],{},"            data.append(value)\n",[261,1187,1188],{"class":263,"line":577},[261,1189,1190],{},"            time.sleep(0.001)  # 1ms = 1kHz\n",[261,1192,1193],{"class":263,"line":583},[261,1194,297],{"emptyLinePlaceholder":296},[261,1196,1197],{"class":263,"line":589},[261,1198,1199],{},"        return np.array(data)\n",[261,1201,1202],{"class":263,"line":595},[261,1203,297],{"emptyLinePlaceholder":296},[261,1205,1206],{"class":263,"line":601},[261,1207,1208],{},"    def extract_features(self, vibration_data):\n",[261,1210,1211],{"class":263,"line":606},[261,1212,1213],{},"        \"\"\"Extract frequency domain features\"\"\"\n",[261,1215,1216],{"class":263,"line":612},[261,1217,1218],{},"        # FFT\n",[261,1220,1221],{"class":263,"line":618},[261,1222,1223],{},"        fft = np.fft.fft(vibration_data)\n",[261,1225,1226],{"class":263,"line":624},[261,1227,1228],{},"        freqs = np.fft.fftfreq(len(vibration_data), d=0.001)\n",[261,1230,1231],{"class":263,"line":630},[261,1232,297],{"emptyLinePlaceholder":296},[261,1234,1235],{"class":263,"line":636},[261,1236,1237],{},"        # Peak frequencies\n",[261,1239,1240],{"class":263,"line":642},[261,1241,1242],{},"        peaks, _ = signal.find_peaks(np.abs(fft), height=100)\n",[261,1244,1245],{"class":263,"line":648},[261,1246,1247],{},"        peak_freqs = freqs[peaks]\n",[261,1249,1250],{"class":263,"line":654},[261,1251,297],{"emptyLinePlaceholder":296},[261,1253,1254],{"class":263,"line":659},[261,1255,1256],{},"        # Statistical features\n",[261,1258,1259],{"class":263,"line":665},[261,1260,1261],{},"        features = {\n",[261,1263,1264],{"class":263,"line":671},[261,1265,1266],{},"            \"rms\": np.sqrt(np.mean(vibration_data**2)),\n",[261,1268,1269],{"class":263,"line":677},[261,1270,1271],{},"            \"peak\": np.max(np.abs(vibration_data)),\n",[261,1273,1274],{"class":263,"line":683},[261,1275,1276],{},"            \"crest_factor\": np.max(np.abs(vibration_data)) / np.sqrt(np.mean(vibration_data**2)),\n",[261,1278,1279],{"class":263,"line":688},[261,1280,1281],{},"            \"dominant_freq\": peak_freqs[0] if len(peak_freqs) > 0 else 0,\n",[261,1283,1284],{"class":263,"line":694},[261,1285,1286],{},"            \"spectral_energy\": np.sum(np.abs(fft)**2)\n",[261,1288,1289],{"class":263,"line":700},[261,1290,1291],{},"        }\n",[261,1293,1294],{"class":263,"line":706},[261,1295,297],{"emptyLinePlaceholder":296},[261,1297,1298],{"class":263,"line":712},[261,1299,1300],{},"        return features\n",[261,1302,1303],{"class":263,"line":718},[261,1304,297],{"emptyLinePlaceholder":296},[261,1306,1307],{"class":263,"line":723},[261,1308,1309],{},"    def predict_with_ai(self, features):\n",[261,1311,1312],{"class":263,"line":729},[261,1313,1314],{},"        \"\"\"Predictive maintenance analysis with AI\"\"\"\n",[261,1316,1317],{"class":263,"line":734},[261,1318,674],{},[261,1320,1321],{"class":263,"line":740},[261,1322,1323],{},"You are a mechanical engineer expert in predictive maintenance. Analyze the following vibration data from an industrial motor:\n",[261,1325,1326],{"class":263,"line":746},[261,1327,297],{"emptyLinePlaceholder":296},[261,1329,1330],{"class":263,"line":752},[261,1331,1332],{},"RMS Vibration: {features['rms']:.3f} m/s²\n",[261,1334,1335],{"class":263,"line":758},[261,1336,1337],{},"Peak Vibration: {features['peak']:.3f} m/s²\n",[261,1339,1340],{"class":263,"line":764},[261,1341,1342],{},"Crest Factor: {features['crest_factor']:.2f}\n",[261,1344,1345],{"class":263,"line":769},[261,1346,1347],{},"Dominant Frequency: {features['dominant_freq']:.1f} Hz\n",[261,1349,1350],{"class":263,"line":775},[261,1351,1352],{},"Spectral Energy: {features['spectral_energy']:.2e}\n",[261,1354,1355],{"class":263,"line":781},[261,1356,297],{"emptyLinePlaceholder":296},[261,1358,1359],{"class":263,"line":786},[261,1360,1361],{},"Reference values:\n",[261,1363,1364],{"class":263,"line":792},[261,1365,1366],{},"- Normal RMS: 0.5-2.0 m/s²\n",[261,1368,1369],{"class":263,"line":798},[261,1370,1371],{},"- Warning RMS: 2.0-5.0 m/s²\n",[261,1373,1374],{"class":263,"line":804},[261,1375,1376],{},"- Critical RMS: >5.0 m/s²\n",[261,1378,1379],{"class":263,"line":810},[261,1380,1381],{},"- Normal Crest Factor: 3-4\n",[261,1383,1384],{"class":263,"line":816},[261,1385,1386],{},"- Motor rotation: 1500 RPM (25 Hz)\n",[261,1388,1389],{"class":263,"line":821},[261,1390,297],{"emptyLinePlaceholder":296},[261,1392,1393],{"class":263,"line":827},[261,1394,1395],{},"Task: Provide predictive maintenance assessment:\n",[261,1397,1398],{"class":263,"line":833},[261,1399,1400],{},"1. Motor condition (Normal/Warning/Critical)\n",[261,1402,1403],{"class":263,"line":838},[261,1404,1405],{},"2. Probable fault type (if any)\n",[261,1407,1408],{"class":263,"line":844},[261,1409,1410],{},"3. Estimated time to failure (days)\n",[261,1412,1413],{"class":263,"line":850},[261,1414,761],{},[261,1416,1417],{"class":263,"line":856},[261,1418,297],{"emptyLinePlaceholder":296},[261,1420,1421],{"class":263,"line":861},[261,1422,772],{},[261,1424,1425],{"class":263,"line":867},[261,1426,778],{},[261,1428,1429],{"class":263,"line":873},[261,1430,297],{"emptyLinePlaceholder":296},[261,1432,1433],{"class":263,"line":878},[261,1434,789],{},[261,1436,1437],{"class":263,"line":884},[261,1438,795],{},[261,1440,1441],{"class":263,"line":890},[261,1442,801],{},[261,1444,1445],{"class":263,"line":895},[261,1446,1447],{},"            format='json'\n",[261,1449,1450],{"class":263,"line":901},[261,1451,813],{},[261,1453,1454],{"class":263,"line":907},[261,1455,297],{"emptyLinePlaceholder":296},[261,1457,1458],{"class":263,"line":912},[261,1459,1460],{},"        return json.loads(response['response'])\n",[261,1462,1463],{"class":263,"line":918},[261,1464,297],{"emptyLinePlaceholder":296},[261,1466,1467],{"class":263,"line":924},[261,1468,973],{},[261,1470,1471],{"class":263,"line":930},[261,1472,1473],{},"    analyzer = VibrationAnalyzer()\n",[261,1475,1476],{"class":263,"line":936},[261,1477,297],{"emptyLinePlaceholder":296},[261,1479,1480],{"class":263,"line":942},[261,1481,1482],{},"    # Read vibration data\n",[261,1484,1485],{"class":263,"line":948},[261,1486,1487],{},"    vibration = analyzer.read_vibration_data(1000)\n",[261,1489,1490],{"class":263,"line":954},[261,1491,297],{"emptyLinePlaceholder":296},[261,1493,1494],{"class":263,"line":959},[261,1495,1496],{},"    # Extract features\n",[261,1498,1499],{"class":263,"line":965},[261,1500,1501],{},"    features = analyzer.extract_features(vibration)\n",[261,1503,1504],{"class":263,"line":970},[261,1505,1506],{},"    print(f\"📊 Features: {features}\")\n",[261,1508,1509],{"class":263,"line":976},[261,1510,297],{"emptyLinePlaceholder":296},[261,1512,1513],{"class":263,"line":982},[261,1514,1515],{},"    # AI prediction\n",[261,1517,1519],{"class":263,"line":1518},91,[261,1520,1521],{},"    prediction = analyzer.predict_with_ai(features)\n",[261,1523,1525],{"class":263,"line":1524},92,[261,1526,1527],{},"    print(f\"\\n🔮 AI Prediction:\")\n",[261,1529,1531],{"class":263,"line":1530},93,[261,1532,1533],{},"    print(json.dumps(prediction, indent=2))\n",[15,1535,1536],{},[19,1537,990],{},[235,1539,1541],{"className":993,"code":1540,"language":995,"meta":244,"style":244},"{\n  \"condition\": \"Warning\",\n  \"fault_type\": \"Bearing wear (outer race)\",\n  \"estimated_ttf_days\": 15,\n  \"confidence\": 0.78,\n  \"recommended_action\": \"Schedule bearing replacement within 2 weeks. Increase monitoring frequency to daily.\",\n  \"evidence\": \"Elevated RMS (3.2 m/s²) and high-frequency components at 250 Hz indicate outer race fault.\"\n}\n",[242,1542,1543,1547,1559,1571,1583,1595,1606,1616],{"__ignoreMap":244},[261,1544,1545],{"class":263,"line":264},[261,1546,1003],{"class":1002},[261,1548,1549,1552,1554,1557],{"class":263,"line":271},[261,1550,1551],{"class":278},"  \"condition\"",[261,1553,1011],{"class":1002},[261,1555,1556],{"class":282},"\"Warning\"",[261,1558,1017],{"class":1002},[261,1560,1561,1564,1566,1569],{"class":263,"line":293},[261,1562,1563],{"class":278},"  \"fault_type\"",[261,1565,1011],{"class":1002},[261,1567,1568],{"class":282},"\"Bearing wear (outer race)\"",[261,1570,1017],{"class":1002},[261,1572,1573,1576,1578,1581],{"class":263,"line":300},[261,1574,1575],{"class":278},"  \"estimated_ttf_days\"",[261,1577,1011],{"class":1002},[261,1579,1580],{"class":278},"15",[261,1582,1017],{"class":1002},[261,1584,1585,1588,1590,1593],{"class":263,"line":306},[261,1586,1587],{"class":278},"  \"confidence\"",[261,1589,1011],{"class":1002},[261,1591,1592],{"class":278},"0.78",[261,1594,1017],{"class":1002},[261,1596,1597,1599,1601,1604],{"class":263,"line":321},[261,1598,1046],{"class":278},[261,1600,1011],{"class":1002},[261,1602,1603],{"class":282},"\"Schedule bearing replacement within 2 weeks. Increase monitoring frequency to daily.\"",[261,1605,1017],{"class":1002},[261,1607,1608,1611,1613],{"class":263,"line":333},[261,1609,1610],{"class":278},"  \"evidence\"",[261,1612,1011],{"class":1002},[261,1614,1615],{"class":282},"\"Elevated RMS (3.2 m/s²) and high-frequency components at 250 Hz indicate outer race fault.\"\n",[261,1617,1618],{"class":263,"line":338},[261,1619,1068],{"class":1002},[10,1621,1623],{"id":1622},"raspberry-pi-5-ollama-edge-ai-solution","Raspberry Pi 5 + Ollama: Edge AI Solution",[70,1625,1627],{"id":1626},"hardware-configuration","Hardware Configuration",[15,1629,1630],{},[19,1631,1632],{},"Components:",[452,1634,1635,1638,1641,1644],{},[455,1636,1637],{},"Raspberry Pi 5 (8GB RAM)",[455,1639,1640],{},"NVMe SSD (256GB) via PCIe",[455,1642,1643],{},"PoE+ HAT (for Ethernet power)",[455,1645,1646],{},"Industrial case with fan",[15,1648,1649],{},[19,1650,1651],{},"Performance:",[112,1653,1654,1667],{},[115,1655,1656],{},[118,1657,1658,1661,1664],{},[121,1659,1660],{},"Model",[121,1662,1663],{},"Inference Speed",[121,1665,1666],{},"RAM Usage",[133,1668,1669,1682,1695],{},[118,1670,1671,1676,1679],{},[138,1672,1673],{},[19,1674,1675],{},"Llama 3.2 (3B)",[138,1677,1678],{},"~15 tokens/sec",[138,1680,1681],{},"2.5GB",[118,1683,1684,1689,1692],{},[138,1685,1686],{},[19,1687,1688],{},"Phi-3 (3.8B)",[138,1690,1691],{},"~12 tokens/sec",[138,1693,1694],{},"3.2GB",[118,1696,1697,1702,1705],{},[138,1698,1699],{},[19,1700,1701],{},"Mistral 7B",[138,1703,1704],{},"~6 tokens/sec",[138,1706,1707],{},"5.8GB",[70,1709,1711],{"id":1710},"setup-script","Setup Script",[235,1713,1715],{"className":255,"code":1714,"language":257,"meta":244,"style":244},"#!/bin/bash\n# install_edge_ai.sh\n\n# Install Ollama on Raspberry Pi 5\ncurl -fsSL https://ollama.com/install.sh | sh\n\n# Download lightweight models\nollama pull llama3.2:3b\nollama pull phi3:mini\n\n# Install Python dependencies\npip3 install ollama pymodbus numpy pandas\n\n# Configure systemd service\ncat > /etc/systemd/system/edge-ai.service \u003C\u003CEOF\n[Unit]\nDescription=Edge AI Monitoring\nAfter=network.target ollama.service\n\n[Service]\nType=simple\nUser=pi\nWorkingDirectory=/opt/edge-ai\nExecStart=/usr/bin/python3 /opt/edge-ai/monitor.py\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\nsystemctl enable edge-ai\nsystemctl start edge-ai\n",[242,1716,1717,1722,1727,1731,1736,1748,1752,1757,1766,1775,1779,1784,1800,1804,1809,1826,1831,1836,1841,1845,1850,1855,1860,1865,1870,1875,1879,1884,1889,1893,1897,1907],{"__ignoreMap":244},[261,1718,1719],{"class":263,"line":264},[261,1720,1721],{"class":267},"#!/bin/bash\n",[261,1723,1724],{"class":263,"line":271},[261,1725,1726],{"class":267},"# install_edge_ai.sh\n",[261,1728,1729],{"class":263,"line":293},[261,1730,297],{"emptyLinePlaceholder":296},[261,1732,1733],{"class":263,"line":300},[261,1734,1735],{"class":267},"# Install Ollama on Raspberry Pi 5\n",[261,1737,1738,1740,1742,1744,1746],{"class":263,"line":306},[261,1739,275],{"class":274},[261,1741,279],{"class":278},[261,1743,283],{"class":282},[261,1745,287],{"class":286},[261,1747,290],{"class":274},[261,1749,1750],{"class":263,"line":321},[261,1751,297],{"emptyLinePlaceholder":296},[261,1753,1754],{"class":263,"line":333},[261,1755,1756],{"class":267},"# Download lightweight models\n",[261,1758,1759,1761,1763],{"class":263,"line":338},[261,1760,347],{"class":274},[261,1762,350],{"class":282},[261,1764,1765],{"class":282}," llama3.2:3b\n",[261,1767,1768,1770,1772],{"class":263,"line":344},[261,1769,347],{"class":274},[261,1771,350],{"class":282},[261,1773,1774],{"class":282}," phi3:mini\n",[261,1776,1777],{"class":263,"line":359},[261,1778,297],{"emptyLinePlaceholder":296},[261,1780,1781],{"class":263,"line":372},[261,1782,1783],{"class":267},"# Install Python dependencies\n",[261,1785,1786,1789,1791,1793,1795,1798],{"class":263,"line":385},[261,1787,1788],{"class":274},"pip3",[261,1790,418],{"class":282},[261,1792,421],{"class":282},[261,1794,427],{"class":282},[261,1796,1797],{"class":282}," numpy",[261,1799,433],{"class":282},[261,1801,1802],{"class":263,"line":390},[261,1803,297],{"emptyLinePlaceholder":296},[261,1805,1806],{"class":263,"line":396},[261,1807,1808],{"class":267},"# Configure systemd service\n",[261,1810,1811,1814,1817,1820,1823],{"class":263,"line":548},[261,1812,1813],{"class":274},"cat",[261,1815,1816],{"class":286}," >",[261,1818,1819],{"class":282}," /etc/systemd/system/edge-ai.service",[261,1821,1822],{"class":286}," \u003C\u003C",[261,1824,1825],{"class":282},"EOF\n",[261,1827,1828],{"class":263,"line":554},[261,1829,1830],{"class":282},"[Unit]\n",[261,1832,1833],{"class":263,"line":560},[261,1834,1835],{"class":282},"Description=Edge AI Monitoring\n",[261,1837,1838],{"class":263,"line":566},[261,1839,1840],{"class":282},"After=network.target ollama.service\n",[261,1842,1843],{"class":263,"line":571},[261,1844,297],{"emptyLinePlaceholder":296},[261,1846,1847],{"class":263,"line":577},[261,1848,1849],{"class":282},"[Service]\n",[261,1851,1852],{"class":263,"line":583},[261,1853,1854],{"class":282},"Type=simple\n",[261,1856,1857],{"class":263,"line":589},[261,1858,1859],{"class":282},"User=pi\n",[261,1861,1862],{"class":263,"line":595},[261,1863,1864],{"class":282},"WorkingDirectory=/opt/edge-ai\n",[261,1866,1867],{"class":263,"line":601},[261,1868,1869],{"class":282},"ExecStart=/usr/bin/python3 /opt/edge-ai/monitor.py\n",[261,1871,1872],{"class":263,"line":606},[261,1873,1874],{"class":282},"Restart=always\n",[261,1876,1877],{"class":263,"line":612},[261,1878,297],{"emptyLinePlaceholder":296},[261,1880,1881],{"class":263,"line":618},[261,1882,1883],{"class":282},"[Install]\n",[261,1885,1886],{"class":263,"line":624},[261,1887,1888],{"class":282},"WantedBy=multi-user.target\n",[261,1890,1891],{"class":263,"line":630},[261,1892,1825],{"class":282},[261,1894,1895],{"class":263,"line":636},[261,1896,297],{"emptyLinePlaceholder":296},[261,1898,1899,1902,1904],{"class":263,"line":642},[261,1900,1901],{"class":274},"systemctl",[261,1903,328],{"class":282},[261,1905,1906],{"class":282}," edge-ai\n",[261,1908,1909,1911,1913],{"class":263,"line":648},[261,1910,1901],{"class":274},[261,1912,315],{"class":282},[261,1914,1906],{"class":282},[10,1916,1918],{"id":1917},"cost-comparison-ollama-vs-cloud-ai","Cost Comparison: Ollama vs Cloud AI",[70,1920,1922],{"id":1921},"scenario-10-devices-continuous-monitoring","Scenario: 10 devices, continuous monitoring",[15,1924,1925],{},[19,1926,1927],{},"Monthly Costs:",[112,1929,1930,1946],{},[115,1931,1932],{},[118,1933,1934,1937,1940,1943],{},[121,1935,1936],{},"Solution",[121,1938,1939],{},"Hardware",[121,1941,1942],{},"Compute",[121,1944,1945],{},"Total",[133,1947,1948,1962,1976],{},[118,1949,1950,1954,1957,1960],{},[138,1951,1952],{},[19,1953,29],{},[138,1955,1956],{},"-",[138,1958,1959],{},"$450/month",[138,1961,1959],{},[118,1963,1964,1969,1971,1974],{},[138,1965,1966],{},[19,1967,1968],{},"OpenAI API",[138,1970,1956],{},[138,1972,1973],{},"$820/month",[138,1975,1973],{},[118,1977,1978,1982,1985,1988],{},[138,1979,1980],{},[19,1981,131],{},[138,1983,1984],{},"$800 (one-time)",[138,1986,1987],{},"$5 (electricity)",[138,1989,1990],{},[19,1991,1992],{},"$5/month",[15,1994,1995,1998],{},[19,1996,1997],{},"ROI:"," Ollama pays for itself in 2 months!",[10,2000,2002],{"id":2001},"conclusion","Conclusion",[15,2004,2005,2007,2008,2011],{},[19,2006,37],{}," enables powerful AI applications in industrial facilities while maintaining ",[19,2009,2010],{},"complete data privacy",". Especially for:",[15,2013,76,2014,2017,84,2019,2022,84,2024,2027,84,2029],{},[19,2015,2016],{},"Factories with confidential production data",[82,2018],{},[19,2020,2021],{},"Facilities without reliable internet",[82,2023],{},[19,2025,2026],{},"Real-time decision making requirements (\u003C100ms)",[82,2028],{},[19,2030,2031],{},"Cost-sensitive projects",[15,2033,2034,2035,22,2038,2041,2042,59],{},"Our ",[47,2036,2037],{"href":49},"ZMA",[47,2039,2040],{"href":53},"GDT"," products can be combined with Ollama to build predictive maintenance systems ",[19,2043,2044],{},"entirely locally",[70,2046,2048],{"id":2047},"related-resources","Related Resources",[452,2050,2051,2058,2065,2069],{},[455,2052,2053,2057],{},[47,2054,2056],{"href":2055},"/en/blog/aws-bedrock-industrial-generative-ai","Industrial AI with AWS Bedrock"," (Cloud alternative)",[455,2059,2060,2064],{},[47,2061,2063],{"href":2062},"/en/blog/tinyml-ai-revolution-industrial-sensors","TinyML: AI Revolution in Industrial Sensors"," (MCU-level AI)",[455,2066,2067],{},[47,2068,50],{"href":49},[455,2070,2071],{},[47,2072,54],{"href":53},[2074,2075,2076],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":244,"searchDepth":271,"depth":271,"links":2078},[2079,2080,2084,2085,2089,2093,2097,2101,2104],{"id":12,"depth":271,"text":13},{"id":62,"depth":271,"text":63,"children":2081},[2082,2083],{"id":72,"depth":293,"text":73},{"id":109,"depth":293,"text":110},{"id":232,"depth":271,"text":233},{"id":247,"depth":271,"text":248,"children":2086},[2087,2088],{"id":251,"depth":293,"text":252},{"id":404,"depth":293,"text":405},{"id":436,"depth":271,"text":437,"children":2090},[2091,2092],{"id":440,"depth":293,"text":441},{"id":466,"depth":293,"text":467},{"id":1071,"depth":271,"text":1072,"children":2094},[2095,2096],{"id":1075,"depth":293,"text":441},{"id":1084,"depth":293,"text":1085},{"id":1622,"depth":271,"text":1623,"children":2098},[2099,2100],{"id":1626,"depth":293,"text":1627},{"id":1710,"depth":293,"text":1711},{"id":1917,"depth":271,"text":1918,"children":2102},[2103],{"id":1921,"depth":293,"text":1922},{"id":2001,"depth":271,"text":2002,"children":2105},[2106],{"id":2047,"depth":293,"text":2048},"Local AI models deployment with Ollama in factories without cloud data transfer for predictive maintenance and anomaly detection applications.","md",{"date":2110,"author":2111,"readTime":372,"tags":2112},"2025-12-29","Amazeng Technical Team",[37,2113,2114,2115,2116,142,2117],"Local AI","Predictive Maintenance","Llama","Edge AI","Industrial AI","/en/blog/on-premise-ai-solutions-with-ollama",{"title":5,"description":2107},"en/blog/on-premise-ai-solutions-with-ollama","mKxsuIH4_TTq3ryFkBdo491ZQAH_cjoLLC8AQhLeSE0",1778229658766]