{
  "source_file": "0930",
  "source_platform": "Medium",
  "author": "Shawhin Talebi",
  "title_listed": "Local LLM Fine-Tuning on Mac (M1 16GB)",
  "keywords": "本地微调,MLX",
  "domain": "大模型算法",
  "content_type": "深度技术解析",
  "is_paid_flag": "部分免费/会员墙",
  "url": "https://towardsdatascience.com/local-llm-fine-tuning-on-mac-m1-16gb-f59f4f598be7/",
  "publish_date": "2024-08",
  "corpus_stage": "预训练/SFT",
  "notes": "",
  "id": "b964b6337d1d",
  "collected_at": "2026-10-01T22:41:51",
  "title": "Local LLM Fine-Tuning on Mac (M1 16GB) | Towards Data Science",
  "body_markdown": "![Revisit consent button](https://cdn-cookieyes.com/assets/images/revisit.svg)\nWe value your privacy\nWe use cookies to enhance your browsing experience, serve personalised ads or content, and analyse our traffic. By clicking \"Accept All\", you consent to our use of cookies.\nCustomise Reject All Accept All\nCustomise Consent Preferences ![](https://cdn-cookieyes.com/assets/images/close.svg)\nWe use cookies to help you navigate efficiently and perform certain functions. You will find detailed information about all cookies under each consent category below.\nThe cookies that are categorised as \"Necessary\" are stored on your browser as they are essential for enabling the basic functionalities of the site. ... Show more\nNecessaryAlways Active\nNecessary cookies are required to enable the basic features of this site, such as providing secure log-in or adjusting your consent preferences. These cookies do not store any personally identifiable data.\n  * Cookie\nBCTempID\n  * Duration\n10 minutes\n  * Description\nNo description available.\n\n\n  * Cookie\n__cf_bm\n  * Duration\n1 hour\n  * Description\nThis cookie, set by Cloudflare, is used to support Cloudflare Bot Management. \n\n\n  * Cookie\nAWSALBCORS\n  * Duration\n7 days\n  * Description\nAmazon Web Services set this cookie for load balancing.\n\n\n  * Cookie\n_cfuvid\n  * Duration\nsession\n  * Description\nCloudflare sets this cookie to track users across sessions to optimize user experience by maintaining session consistency and providing personalized services\n\n\n  * Cookie\nli_gc\n  * Duration\n6 months\n  * Description\nLinkedin set this cookie for storing visitor's consent regarding using cookies for non-essential purposes.\n\n\n  * Cookie\n__hssrc\n  * Duration\nsession\n  * Description\nThis cookie is set by Hubspot whenever it changes the session cookie. The __hssrc cookie set to 1 indicates that the user has restarted the browser, and if the cookie does not exist, it is assumed to be a new session.\n\n\n  * Cookie\n__hssc\n  * Duration\n1 hour\n  * Description\nHubSpot sets this cookie to keep track of sessions and to determine if HubSpot should increment the session number and timestamps in the __hstc cookie.\n\n\n  * Cookie\nwpEmojiSettingsSupports\n  * Duration\nsession\n  * Description\nWordPress sets this cookie when a user interacts with emojis on a WordPress site. It helps determine if the user's browser can display emojis properly.\n\n\n  * Cookie\nBCSessionID\n  * Duration\n1 year 1 month 4 days\n  * Description\nBlueconic sets this cookie as a unique identifier for the BlueConic profile.\n\n\n  * Cookie\n_octo\n  * Duration\n1 year\n  * Description\nNo description available.\n\n\n  * Cookie\nlogged_in\n  * Duration\n1 year\n  * Description\nNo description available.\n\n\n  * Cookie\n__Secure-YEC\n  * Duration\npast\n  * Description\nYouTube sets this cookie to stores the user's video player preferences using embedded YouTube video\n\n\n  * Cookie\n__eoi\n  * Duration\n6 months\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nAWSALBTGCORS\n  * Duration\n7 days\n  * Description\nNo description available.\n\n\n  * Cookie\nlogin-status-p\n  * Duration\npast\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nAWSALBTG\n  * Duration\n7 days\n  * Description\nNo description available.\n\n\n  * Cookie\ncsrf_token\n  * Duration\nsession\n  * Description\nNo description available.\n\n\n  * Cookie\ntoken_v2\n  * Duration\n1 day\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nD\n  * Duration\n1 year\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nPHPSESSID\n  * Duration\nsession\n  * Description\nThis cookie is native to PHP applications. The cookie stores and identifies a user's unique session ID to manage user sessions on the website. The cookie is a session cookie and will be deleted when all the browser windows are closed.\n\n\n  * Cookie\nVISITOR_PRIVACY_METADATA\n  * Duration\n6 months\n  * Description\nYouTube sets this cookie to store the user's cookie consent state for the current domain. \n\n\n  * Cookie\ncookietest\n  * Duration\nsession\n  * Description\nThe cookietest cookie is typically used to determine whether the user's browser accepts cookies, essential for website functionality and user experience.\n\n\n  * Cookie\n__Host-airtable-session\n  * Duration\n1 year\n  * Description\nThis cookie is used to enable us to integrate the services of Airtable.\n\n\n  * Cookie\n__Host-airtable-session.sig\n  * Duration\n1 year\n  * Description\nThis cookie is used to enable us to integrate the services of Airtable.\n\n\n  * Cookie\nm\n  * Duration\n1 year 1 month 4 days\n  * Description\nStripe sets this cookie for fraud prevention purposes. It identifies the device used to access the website, allowing the website to be formatted accordingly.\n\n\n  * Cookie\nBIGipServer*\n  * Duration\nsession\n  * Description\nMarketo sets this cookie to collect information about the user's online activity and build a profile about their interests to provide advertisements relevant to the user. \n\n\n  * Cookie\n__cfruid\n  * Duration\nsession\n  * Description\nCloudflare sets this cookie to identify trusted web traffic.\n\n\n  * Cookie\n_GRECAPTCHA\n  * Duration\n6 months\n  * Description\nGoogle Recaptcha service sets this cookie to identify bots to protect the website against malicious spam attacks.\n\n\n  * Cookie\n__Secure-YNID\n  * Duration\n6 months\n  * Description\nGoogle cookie used to protect user security and prevent fraud, especially during the login process.\n\n\n  * Cookie\ncookieyes-consent\n  * Duration\n1 year\n  * Description\nCookieYes sets this cookie to remember users' consent preferences so that their preferences are respected on subsequent visits to this site. It does not collect or store any personal information about the site visitors.\n\n\nFunctional\nFunctional cookies help perform certain functionalities like sharing the content of the website on social media platforms, collecting feedback, and other third-party features.\n  * Cookie\nlidc\n  * Duration\n1 day\n  * Description\nLinkedIn sets the lidc cookie to facilitate data center selection.\n\n\n  * Cookie\nbrw\n  * Duration\n1 year\n  * Description\nNo description available.\n\n\n  * Cookie\nbrwConsent\n  * Duration\n5 minutes\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nWMF-Uniq\n  * Duration\n1 year\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nloom_anon_comment\n  * Duration\n1 year\n  * Description\nNo description available.\n\n\n  * Cookie\nloom_referral_video\n  * Duration\nsession\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nVISITOR_INFO1_LIVE\n  * Duration\n6 months\n  * Description\nA cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface.\n\n\n  * Cookie\nyt-remote-connected-devices\n  * Duration\nNever Expires\n  * Description\nYouTube sets this cookie to store the user's video preferences using embedded YouTube videos.\n\n\n  * Cookie\nytidb::LAST_RESULT_ENTRY_KEY\n  * Duration\nNever Expires\n  * Description\nThe cookie ytidb::LAST_RESULT_ENTRY_KEY is used by YouTube to store the last search result entry that was clicked by the user. This information is used to improve the user experience by providing more relevant search results in the future.\n\n\n  * Cookie\nyt-remote-device-id\n  * Duration\nNever Expires\n  * Description\nYouTube sets this cookie to store the user's video preferences using embedded YouTube videos.\n\n\n  * Cookie\nyt-remote-session-name\n  * Duration\nsession\n  * Description\nThe yt-remote-session-name cookie is used by YouTube to store the user's video player preferences using embedded YouTube video.\n\n\n  * Cookie\nyt-remote-fast-check-period\n  * Duration\nsession\n  * Description\nThe yt-remote-fast-check-period cookie is used by YouTube to store the user's video player preferences for embedded YouTube videos.\n\n\n  * Cookie\nyt-remote-session-app\n  * Duration\nsession\n  * Description\nThe yt-remote-session-app cookie is used by YouTube to store user preferences and information about the interface of the embedded YouTube video player.\n\n\n  * Cookie\nyt-remote-cast-available\n  * Duration\nsession\n  * Description\nThe yt-remote-cast-available cookie is used to store the user's preferences regarding whether casting is available on their YouTube video player.\n\n\n  * Cookie\nyt-remote-cast-installed\n  * Duration\nsession\n  * Description\nThe yt-remote-cast-installed cookie is used to store the user's video player preferences using embedded YouTube video.\n\n\n  * Cookie\ncp_session\n  * Duration\n3 months\n  * Description\nCodepen sets this cookie for Help systems found in the website.\n\n\n  * Cookie\nloid\n  * Duration\n1 year 1 month 4 days\n  * Description\nThis cookie is set by the Reddit. The cookie enables the sharing of content from the website onto the social media platform.\n\n\nAnalytics\nAnalytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics such as the number of visitors, bounce rate, traffic source, etc.\n  * Cookie\n__hstc\n  * Duration\n6 months\n  * Description\nHubspot set this main cookie for tracking visitors. It contains the domain, initial timestamp (first visit), last timestamp (last visit), current timestamp (this visit), and session number (increments for each subsequent session).\n\n\n  * Cookie\nhubspotutk\n  * Duration\n6 months\n  * Description\nHubSpot sets this cookie to keep track of the visitors to the website. This cookie is passed to HubSpot on form submission and used when deduplicating contacts.\n\n\n  * Cookie\n_ga\n  * Duration\n1 year 1 month 4 days\n  * Description\nGoogle Analytics sets this cookie to calculate visitor, session and campaign data and track site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognise unique visitors.\n\n\n  * Cookie\n_ga_*\n  * Duration\n1 year 1 month 4 days\n  * Description\nGoogle Analytics sets this cookie to store and count page views.\n\n\n  * Cookie\n__Host-psifi.analyticsTrace\n  * Duration\n6 hours\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\n__Host-psifi.analyticsTraceV2\n  * Duration\n6 hours\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\n_gh_sess\n  * Duration\nsession\n  * Description\nGitHub sets this cookie for temporary application and framework state between pages like what step the user is on in a multiple step form.\n\n\n  * Cookie\nYSC\n  * Duration\nsession\n  * Description\nYSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages.\n\n\n  * Cookie\najs_anonymous_id\n  * Duration\n1 year\n  * Description\nThis cookie is set by Segment to count the number of people who visit a certain site by tracking if they have visited before.\n\n\n  * Cookie\nvuid\n  * Duration\n1 year 1 month 4 days\n  * Description\nVimeo installs this cookie to collect tracking information by setting a unique ID to embed videos on the website. \n\n\nPerformance\nPerformance cookies are used to understand and analyse the key performance indexes of the website which helps in delivering a better user experience for the visitors.\n  * Cookie\nAWSALB\n  * Duration\n7 days\n  * Description\nAWSALB is an application load balancer cookie set by Amazon Web Services to map the session to the target.\n\n\n  * Cookie\nacq\n  * Duration\npast\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nacq.sig\n  * Duration\npast\n  * Description\nDescription is currently not available.\n\n\n  * Cookie\nptc\n  * Duration\n2 years\n  * Description\nNo description available.\n\n\nAdvertisement\nAdvertisement cookies are used to provide visitors with customised advertisements based on the pages you visited previously and to analyse the effectiveness of the ad campaigns.\n  * Cookie\nmuc_ads\n  * Duration\n1 year 1 month 4 days\n  * Description\nTwitter sets this cookie to collect user behaviour and interaction data to optimize the website.\n\n\n  * Cookie\nguest_id_marketing\n  * Duration\n1 year 1 month 4 days\n  * Description\nTwitter sets this cookie to identify and track the website visitor.\n\n\n  * Cookie\nguest_id_ads\n  * Duration\n1 year 1 month 4 days\n  * Description\nTwitter sets this cookie to identify and track the website visitor.\n\n\n  * Cookie\npersonalization_id\n  * Duration\n1 year 1 month 4 days\n  * Description\nTwitter sets this cookie to integrate and share features for social media and also store information about how the user uses the website, for tracking and targeting.\n\n\n  * Cookie\nguest_id\n  * Duration\n1 year 1 month 4 days\n  * Description\nTwitter sets this cookie to identify and track the website visitor. It registers if a user is signed in to the Twitter platform and collects information about ad preferences.\n\n\n  * Cookie\nbcookie\n  * Duration\n1 year\n  * Description\nLinkedIn sets this cookie from LinkedIn share buttons and ad tags to recognize browser IDs.\n\n\n  * Cookie\n__Secure-ROLLOUT_TOKEN\n  * Duration\n6 months\n  * Description\nYouTube sets this cookie to manage feature rollout and experimentation. It helps Google control which new features or interface changes are shown to users as part of testing and staged rollouts, ensuring consistent experience for a given user during an experiment.\n\n\n  * Cookie\nyt.innertube::nextId\n  * Duration\nNever Expires\n  * Description\nYouTube sets this cookie to register a unique ID to store data on what videos from YouTube the user has seen.\n\n\n  * Cookie\nyt.innertube::requests\n  * Duration\nNever Expires\n  * Description\nYouTube sets this cookie to register a unique ID to store data on what videos from YouTube the user has seen.\n\n\n  * Cookie\nsession_tracker\n  * Duration\nsession\n  * Description\nThis cookie is set by the Reddit. This cookie is used to identify trusted web traffic. It also helps in adverstising on the website.\n\n\n  * Cookie\nedgebucket\n  * Duration\nsession\n  * Description\nReddit sets this cookie to save the information about a log-on Reddit user, for the purpose of advertisement recommendations and updating the content.\n\n\n  * Cookie\ndid\n  * Duration\n1 year\n  * Description\nArbor sets this cookie to show targeted ads to site visitors.This cookie expires after 2 months or 1 year.\n\n\nUncategorised\nOther uncategorised cookies are those that are being analysed and have not been classified into a category as yet.\nNo cookies to display.\nReject All Save My Preferences Accept All\nToggle Search[](https://towardsdatascience.com/)Toggle Mobile Navigation\n[](https://towardsdatascience.com/)\nPublish AI, ML & data-science insights to a global community of data professionals.\nSign in[Submit an Article](https://write.insightmediagroup.io)\n[Latest](https://towardsdatascience.com/latest/)[Editor's Picks](https://towardsdatascience.com/tag/editors-pick/)[Newsletter](https://towardsdatascience.com/tag/the-variable/)[ShipAI](https://towardsdatascience.com/shipai/)\n* * *\n[Write For TDS](https://towardsdatascience.com/submissions/)\n[LinkedIn](https://www.linkedin.com/company/towards-data-science/)[X](https://x.com/TDataScience)Toggle Search\n[Large Language Models](https://towardsdatascience.com/category/artificial-intelligence/large-language-models/)\n# Local LLM Fine-Tuning on Mac (M1 16GB)\nBeginner-friendly Python code walkthrough (ft. MLX)\n[Shaw Talebi](https://towardsdatascience.com/author/shawhin/)\nAugust 1, 20248 min read\nThis article is part of a [larger series](https://shawhin.medium.com/list/large-language-models-llms-8e009ae3054c) on using large language models (LLMs) in practice. In a [previous post](https://towardsdatascience.com/qlora-how-to-fine-tune-an-llm-on-a-single-gpu-4e44d6b5be32), I showed how to fine-tune an LLM using a single (free) GPU on Google Colab. While that example (and many others) readily runs on Nvidia hardware, they are not easily adapted to M-series Macs. In this article, I walk through an easy way to fine-tune an LLM locally on a Mac.\n![Photo by Myron Mott on Unsplash](https://assets.insightmediagroup.io/media/wp-content/uploads/2024/08/07-r3F1guQD-CUR3v-scaled.jpg)\nPhoto by [Myron Mott](https://unsplash.com/@s2killa?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)\n* * *\nWith the rise of open-source large language models (LLMs) and efficient fine-tuning methods, building custom ML solutions has never been easier. Now, anyone with **a single GPU can fine-tune an LLM on their local machine**.\nHowever, Mac users have been largely left out of this trend due to Apple's M-series chips. These chips employ a unified memory framework, which precludes the need for a GPU. Thus, many (GPU-centric) open-source tools for running and training LLMs are not compatible with (or don't fully utilize) modern Mac computing power.\nI had **almost** given up on my dreams of training LLMs locally until I discovered the MLX Python library.\nLearn this step by step with the interactive [AI Engineer](https://roadmap.sh/ai-engineer) roadmap.\n## **MLX**\n[**MLX**](https://ml-explore.github.io/mlx/build/html/index.html) is a Python library developed by Apple's Machine Learning research team to **run matrix operations efficiently on Apple silicon**. This is important because matrix operations are the core computations underlying neural networks.\nThe key benefit of MLX is it fully utilizes the M series chips' **unified memory paradigm** , which enables modest systems (like mine - M1 16GB) to run fine-tuning jobs on large models (e.g., Mistral 7b Instruct).\nWhile the library doesn't have high-level abstractions for training models like Hugging Face, there is an [example implementation of LoRA](https://github.com/ml-explore/mlx-examples/tree/main/lora) that can be readily hacked and adapted for another use case.\nThis is exactly what I do in the example below.\n## **Example Code: Fine-tuning Mistral 7b Instruct**\nThis example is similar to one from a [previous article](https://towardsdatascience.com/qlora-how-to-fine-tune-an-llm-on-a-single-gpu-4e44d6b5be32). However, instead of using Hugging Face's Transformers library and Google Colab, I will use the MLX library and my local machine (2020 Mac Mini M1 16GB).\nSimilar to the [previous example](https://towardsdatascience.com/qlora-how-to-fine-tune-an-llm-on-a-single-gpu-4e44d6b5be32), I will be **fine-tuning a quantized version of Mistral-7b-Instruct to respond to YouTube comments in my likeness**. I use the QLoRA parameter efficient fine-tuning method. If you are unfamiliar with QLoRA, I have an overview of the method [here](https://towardsdatascience.com/qlora-how-to-fine-tune-an-llm-on-a-single-gpu-4e44d6b5be32).\n> [**QLoRA - How to Fine-Tune an LLM on a Single GPU**](https://towardsdatascience.com/qlora-how-to-fine-tune-an-llm-on-a-single-gpu-4e44d6b5be32)\n🔗 [GitHub Repo](https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx) | [Training Data](https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx/data) | [Pre-trained Model](https://huggingface.co/mlx-community/Mistral-7B-Instruct-v0.2-4bit)\n* * *\n### **1) Setting Up Environment**\nBefore we run the example code, we will need to set up our Python environment. The first step is downloading the code from the [GitHub repo](https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx).\nbash\n\n```\ngit clone https://github.com/ShawhinT/YouTube-Blog.git\n```\n\nThe code for this example is in the _LLMs/qlora-mlx_ subdirectory. We can navigate to this folder and create a new Python env (here, I call it _mlx-env_).\nbash\n\n```\n# change dir\ncd LLMs/qlora-mlx\n\n# create py venv\npython -m venv mlx-env\n```\n\nNext, we activate the environment and install the requirements from the requirements.txt file. _Note: mlx requires your system to have an M series chip, Python >= 3.8, and macOS >= 13.5_.\nbash\n\n```\n# activate venv\nsource mlx-env/bin/activate\n\n# install requirements\npip install -r requirements.txt\n```\n\n### **2) Inference with Un-finetuned Model**\nNow that we have _mlx_ and other dependencies installed, let's run some Python code! We start by importing helpful libraries.\npython\n\n```\n# import modules (this is Python code now)\nimport subprocess\nfrom mlx_lm import load, generate\n```\n\nWe will use the _subprocess_ module to run terminal commands via Python and the _mlx-lm_ library to run inference on our pre-trained model.\n_mlx-lm_ is built on top of _mlx_ and is **specifically made for running models from the Hugging Face hub**. Here's how we can use it to generate text from an existing model.\npython\n\n```\n# define inputs\nmodel_path = \"mlx-community/Mistral-7B-Instruct-v0.2-4bit\"\nprompt = prompt_builder(\"Great content, thank you!\")\nmax_tokens = 140\n\n# load model\nmodel, tokenizer = load(model_path)\n\n# generate response\nresponse = generate(model, tokenizer, prompt=prompt, \n                                      max_tokens = max_tokens, \n                                      verbose=True)\n```\n\n_Note: Any of the hundreds of models on the Hugging Face_[ _mlx-community page_](https://huggingface.co/mlx-community) _can be readily used for inference. If you want to use a model that isn't available (unlikely), you can use the_[ _scripts/convert.py_](https://github.com/ShawhinT/YouTube-Blog/blob/main/LLMs/qlora-mlx/scripts/convert.py) _script to convert it into a compatible format._\nThe _prompt _builder()_ function takes in a YouTube comment and integrates it into a prompt template, as shown below.\npython\n\n```\n# prompt format\nintstructions_string = f\"\"\"ShawGPT, functioning as a virtual data science \nconsultant on YouTube, communicates in clear, accessible language, escalating \nto technical depth upon request. \nIt reacts to feedback aptly and ends responses with its signature '–ShawGPT'. \nShawGPT will tailor the length of its responses to match the viewer's comment, \nproviding concise acknowledgments to brief expressions of gratitude or \nfeedback, thus keeping the interaction natural and engaging.\n\nPlease respond to the following comment.\n\"\"\"\n\n# define lambda function\nprompt_builder = lambda comment: f'''<s>[INST] {intstructions_string} n{comment} n[/INST]n'''\n```\n\nHere's how the model responds to the comment \"_Great content, thank you!_ \" **without fine-tuning**.\ntext\n\n```\n–ShawGPT: Thank you for your kind words! I'm glad you found the content helpful\nand enjoyable. If you have any specific questions or topics you'd like me to \ncover in more detail, feel free to ask!\n```\n\nWhile the response is coherent, there are **2 main problems** with it. 1) the signature \"-ShawGPT\" is placed at the front of the response instead of the end (as instructed), and 2) the response is much longer than how I would _actually_ respond to a comment like this.\n### **3) Preparing Training Data**\nBefore we can run the fine-tuning job, we must **prepare training, testing, and validation datasets**. Here, I use 50 real comments and responses from my YouTube channel for training and 10 comments/responses for validation and testing (70 total examples).\nA training example is given below. It is in the JSON format, i.e., a key-value pair where the key = \"text\" and the value = the merged prompt, comment, and response.\njson\n\n```\n{\"text\": \"<s>[INST] ShawGPT, functioning as a virtual data science consultant \non YouTube, communicates in clear, accessible language, escalating to technical\n depth upon request. It reacts to feedback aptly and ends responses with its \nsignature 'u2013ShawGPT'. ShawGPT will tailor the length of its responses to \nmatch the viewer's comment, providing concise acknowledgments to brief \nexpressions of gratitude or feedback, thus keeping the interaction natural and \nengaging.nnPlease respond to the following comment.n nThis was a very \nthorough introduction to LLMs and answered many questions I had. Thank you. \nn[/INST]nGreat to hear, glad it was helpful :) -ShawGPT</s>\"}\n```\n\nThe code to generate the train, test, and val datasets from a .csv file is available on [GitHub](https://github.com/ShawhinT/YouTube-Blog/blob/main/LLMs/qlora-mlx/data/prep-data.ipynb).\n### **4) Fine-tuning Model**\nWith our training data prepared, we can fine-tune our model. Here, I use the [_lora.py_](https://github.com/ml-explore/mlx-examples/blob/main/lora/lora.py) example script created by the _mlx_ team.\nThis script is saved in the [_scripts_](https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx/scripts) folder of the repo we cloned, and the train/test/val [data](https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx/data) are saved in the _data_ folder. To run the fine-tuning job, we can run the following terminal command.\nbash\n\n```\npython scripts/lora.py --model mlx-community/Mistral-7B-Instruct-v0.2-4bit \n                       --train \n                       --iters 100 \n                       --steps-per-eval 10 \n                       --val-batches -1 \n                       --learning-rate 1e-5 \n                       --lora-layers 16 \n                       --test\n\n# --train = runs LoRA training\n# --iters = number of training steps\n# --steps-per-eval = number steps to do before computing val loss\n# --val-batches = number val dataset examples to use in val loss (-1 = all)\n# --learning-rate (same as default)\n# --lora-layers (same as default)\n# --test = computes test loss at the end of training\n```\n\nTo have training run as quickly as possible, I closed out all other processes on my machine to allocate as much memory as possible to the fine-tuning process. On my M1 with 16GB of memory, this took about **15–20 minutes** to run and peaked at around **13–14 GB of memory**.\n_Note: I had to make one change in lines 340–341 of the_[ _lora.py script_](https://github.com/ml-explore/mlx-examples/blob/main/lora/lora.py) _to avoid overfitting, which was changing the rank of the LoRA adapters from r=8 to r=4._\n### **5) Inference with Fine-tuned Model**\nOnce training is complete, a file called _adapters.npz_ will appear in the working directory. This contains the LoRA adapter weights.\nTo run inference with these, we can again use the _lora.py._ This time, however, instead of running the script directly from the terminal, I used the _subprocess_ module to run the script in Python. This allows me to use the _prompt _builder()_ function defined earlier.\npython\n\n```\n# define inputs\nadapter_path = \"adapters.npz\" # same as default\nmax_tokens_str = \"140\" # must be string\n\n# define command\ncommand = ['python', 'scripts/lora.py', '--model', model_path, \n                                        '--adapter-file', adapter_path, \n                                        '--max-tokens', max_tokens_str, \n                                        '--prompt', prompt]\n\n# run command and print results continuously\nrun_command_with_live_output(command)\n```\n\nThe _run_command_with_live _output()_ is a helper function (courtesy of ChatGPT) that **continuously prints process outputs from the terminal command**. This avoids having to wait until inference is done to see any outputs.\npython\n\n```\ndef run_command_with_live_output(command: list[str]) -> None:\n    \"\"\"\n    Courtesy of ChatGPT:\n    Runs a command and prints its output line by line as it executes.\n\n    Args:\n        command (List[str]): The command and its arguments to be executed.\n\n    Returns:\n        None\n    \"\"\"\n    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)\n\n    # Print the output line by line\n    while True:\n        output = process.stdout.readline()\n        if output == '' and process.poll() is not None:\n            break\n        if output:\n            print(output.strip())\n\n    # Print the error output, if any\n    err_output = process.stderr.read()\n    if err_output:\n        print(err_output)\n```\n\nHere's how the model responds to the same comment (_Great content, thank you!_), but now **after fine-tuning**.\ntext\n\n```\nGlad you enjoyed it! -ShawGPT\n```\n\nThis response is much better than before fine-tuning. The \"-ShawGPT\" signature is in the right place, and it sounds like something I would _actually_ say.\nBut that's an easy comment to respond to. Let's look at something more challenging, like the one below.\ntext\n\n```\nComment: \nI discovered your channel yesterday and I am hucked, great job. \nIt would be nice to see a video of fine tuning ShawGPT using HF, I saw a video \nyou did running on Colab using Mistal-7b, any chance to do a video using your \nlaptop (Mac) or using HF spaces?\n```\n\ntext\n\n```\nResponse:\nThanks, glad you enjoyed it! I'm looking forward to doing a fine tuning video \non my laptop. I've got an M1 Mac Mini that runs the latest versions of the HF \nAPI. -ShawGPT\n```\n\nAt first glance, this is a great response. The model responds appropriately and does a proper sign-off. It also gets lucky in saying I have a M1 Mac Mini 😉\nHowever, there are two issues with this. First, Mac Minis are desktops, not laptops. Second, the example doesn't directly use the HF API.\n## What's Next?\nHere, I shared a simple local fine-tuning example for M-series Macs. The data and code for this example are freely available on the [GitHub repo](https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx).\nI hope that this can be a helpful jumping-off point for your use cases. If you have **any suggestions for future content** in this series, please let me know in the comments :)\n**More on LLMs 👇**\n> [**Large Language Models (LLMs)**](https://shawhin.medium.com/list/8e009ae3054c)\n* * *\n## Resources\n**Connect** : [My website](https://shawhintalebi.com/) | [Book a call](https://calendly.com/shawhintalebi)\n**Socials** : [YouTube 🎥 ](https://www.youtube.com/channel/UCa9gErQ9AE5jT2DZLjXBIdA) | [LinkedIn](https://www.linkedin.com/in/shawhintalebi/) | [Instagram](https://www.instagram.com/shawhintalebi)\n**Support** : [Buy me a coffee](https://www.buymeacoffee.com/shawhint) ☕️\n> [**Get FREE access to every new story I write**](https://shawhin.medium.com/subscribe)\n* * *\n[1] [MLX](https://ml-explore.github.io/mlx/build/html/index.html)\n[2] [Original code](https://github.com/ml-explore/mlx-examples/tree/main/lora)\n[3] [LoRA paper](https://arxiv.org/abs/2106.09685)\n## Register Now to Continue Reading\n### Unlock Towards Data Science with a Free Account\nAll articles on Towards Data Science are available to registered users. Create a free account today to access this article and thousands more.\nRegister for freeSign in to your account\n* * *\n![](https://assets.insightmediagroup.io/media/1787657074748_utev3i.jpeg)\nWritten By\n## [Shaw Talebi](https://towardsdatascience.com/author/shawhin/)\n[See all from Shaw Talebi](https://towardsdatascience.com/author/shawhin/)\n[Hands On Tutorials](https://towardsdatascience.com/tag/hands-on-tutorials/)[Large Language Models](https://towardsdatascience.com/tag/large-language-models/)[Llm](https://towardsdatascience.com/tag/llm/)[Mac](https://towardsdatascience.com/tag/mac/)[Python](https://towardsdatascience.com/tag/python/)\nShare This Article\n  * [](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Ftowardsdatascience.com%2Flocal-llm-fine-tuning-on-mac-m1-16gb-f59f4f598be7%2F&title=Local%20LLM%20Fine-Tuning%20on%20Mac%20\\(M1%2016GB\\))\n  * [](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Ftowardsdatascience.com%2Flocal-llm-fine-tuning-on-mac-m1-16gb-f59f4f598be7%2F&title=Local%20LLM%20Fine-Tuning%20on%20Mac%20\\(M1%2016GB\\))\n  * [](https://x.com/share?url=https%3A%2F%2Ftowardsdatascience.com%2Flocal-llm-fine-tuning-on-mac-m1-16gb-f59f4f598be7%2F&text=Local%20LLM%20Fine-Tuning%20on%20Mac%20\\(M1%2016GB\\))\n\n\nTowards Data Science is a community publication. Submit your insights to reach our global audience and earn through the TDS Author Payment Program.\n[Write for TDS](https://towardsdatascience.com/submissions/)\n## Related Articles\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2020/09/0IPNvWBtK0p96PHMR-scaled.jpg)](https://towardsdatascience.com/my-experience-as-a-bertelsmann-tech-and-deep-learning-nanodegree-graduate-459ab27db477/)\n## [My Experience as a Bertelsmann Tech and Deep Learning Nanodegree Graduate](https://towardsdatascience.com/my-experience-as-a-bertelsmann-tech-and-deep-learning-nanodegree-graduate-459ab27db477/)\n[Deep Learning](https://towardsdatascience.com/category/artificial-intelligence/deep-learning/)\nThe year 2020 is almost at an end, and this is one of the amazing experience I had in it.\n[Muhammad Rake Linggar Anggoro](https://towardsdatascience.com/author/mrakelinggar/)\nSeptember 19, 20208 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2025/10/image-93.jpg)](https://towardsdatascience.com/how-to-perform-effective-agentic-context-engineering/)\n## [How to Perform Effective Agentic Context Engineering](https://towardsdatascience.com/how-to-perform-effective-agentic-context-engineering/)\n[Large Language Models](https://towardsdatascience.com/category/artificial-intelligence/large-language-models/)\nLearn how to optimize the context of your agents, for powerful agentic performance\n[Eivind Kjosbakken](https://towardsdatascience.com/author/oieivind/)\nOctober 7, 202512 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2022/05/00oIEezKoAUE_IvMN-scaled.jpg)](https://towardsdatascience.com/how-to-read-multiple-csv-files-non-iteratively-and-without-pandas-984fd954999c/)\n## [How To Read Multiple CSV Files Non-Iteratively (and Without Pandas)](https://towardsdatascience.com/how-to-read-multiple-csv-files-non-iteratively-and-without-pandas-984fd954999c/)\n[Artificial Intelligence](https://towardsdatascience.com/category/artificial-intelligence/)\nSay no to Pandas' Read CSV method!\n[Avi Chawla](https://towardsdatascience.com/author/avi_chawla/)\nMay 30, 20223 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2020/06/1Irnlz68vLXEApqIhnCPMww.jpeg)](https://towardsdatascience.com/python-the-unofficial-oop-crash-course-for-aspiring-data-scientists-ed2ed3789bcf/)\n## [Python: The (unofficial) OOP crash course for (aspiring) data scientists!](https://towardsdatascience.com/python-the-unofficial-oop-crash-course-for-aspiring-data-scientists-ed2ed3789bcf/)\n[Machine Learning](https://towardsdatascience.com/category/artificial-intelligence/machine-learning/)\nClasses, attributes, methods, inheritance, encapsulation, and all that other mumbo jumbo you're not sure if you really need (spoiler: for...\n[Jake](https://towardsdatascience.com/author/jacob.d.moore1/)\nJune 16, 20206 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2024/09/1tmtCocWuoHpCVd-VZSwh1g.png)](https://towardsdatascience.com/timesfm-the-boom-of-foundation-models-in-time-series-forecasting-29701e0b20b5/)\n## [TimesFM: The Boom of Foundation Models in Time Series Forecasting](https://towardsdatascience.com/timesfm-the-boom-of-foundation-models-in-time-series-forecasting-29701e0b20b5/)\n[Artificial Intelligence](https://towardsdatascience.com/category/artificial-intelligence/)\nExplore How Google's Latest AI Model Delivers Zero-Shot Forecasting Accuracy Using Over 307 Billion Data Points\n[Luís Roque](https://towardsdatascience.com/author/luisroque/)\nSeptember 20, 202412 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2026/08/fig-a-attention@3x-scaled-1.jpg)](https://towardsdatascience.com/how-a-frontier-model-gets-built-read-from-the-kimi-k3-report/)\n## [How a Frontier Model Gets Built, Read from the Kimi K3 Report](https://towardsdatascience.com/how-a-frontier-model-gets-built-read-from-the-kimi-k3-report/)\n[Large Language Models](https://towardsdatascience.com/category/artificial-intelligence/large-language-models/)\nMoonshot's forty-seven-page report on its open frontier model spends surprisingly little of itself on the model. Most of it is environments, reward design, and serving economics - the parts closed labs never publish.\n[Sean Moran](https://towardsdatascience.com/author/sean.moran/)\nAugust 5, 202621 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2023/08/15pzkKDlj_0cuNsIoNOynAw-scaled.jpeg)](https://towardsdatascience.com/googles-latest-approaches-to-multimodal-foundational-model-beedaced32f9/)\n## [Google's Latest Approaches to Multimodal Foundational Model](https://towardsdatascience.com/googles-latest-approaches-to-multimodal-foundational-model-beedaced32f9/)\n[Large Language Models](https://towardsdatascience.com/category/artificial-intelligence/large-language-models/)\nMultimodal foundational models are even more exciting than large language models. This article reviews Google research's latest progress.\n[Eileen Pangu](https://towardsdatascience.com/author/eileen-code4fun/)\nAugust 12, 20237 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2020/10/1mlR8YGZAtYSSOwRLVRAXwQ.png)](https://towardsdatascience.com/data-visualization-how-nafta-countries-are-doing-in-the-pandemic-a5ef8216e418/)\n## [Data visualization: How NAFTA countries are doing in the pandemic](https://towardsdatascience.com/data-visualization-how-nafta-countries-are-doing-in-the-pandemic-a5ef8216e418/)\n[Data Science](https://towardsdatascience.com/category/data-science/)\nTime at home during the pandemic\n[Thyall D'greville](https://towardsdatascience.com/author/thyalldgreville/)\nOctober 1, 20203 min read\n  * [![](https://assets.insightmediagroup.io/media/wp-content/uploads/2023/08/1EQi-v0WKNCVXDldViCUPvg.png)](https://towardsdatascience.com/what-is-edi-electronic-data-interchange-92f7215bb699/)\n## [What is EDI? Electronic Data Interchange](https://towardsdatascience.com/what-is-edi-electronic-data-interchange-92f7215bb699/)\n[Data Science](https://towardsdatascience.com/category/data-science/)\nExplore how Electronic Data Interchange (EDI) facilitates modern supply chain management.\n[Samir Saci](https://towardsdatascience.com/author/s-saci95/)\nAugust 29, 202311 min read\n\n\n  * [YouTube](https://www.youtube.com/c/TowardsDataScience)\n  * [X](https://x.com/TDataScience)\n  * [LinkedIn](https://www.linkedin.com/company/towards-data-science/)\n  * [Threads](https://www.threads.net/@towardsdatascience)\n  * [Bluesky](https://bsky.app/profile/towardsdatascience.com)\n\n\n[](https://towardsdatascience.com/)\nYour home for data science and AI. The world's leading publication for data science, data analytics, data engineering, machine learning, and artificial intelligence professionals.\nSubscribe to Our Newsletter[Write For TDS](https://towardsdatascience.com/submissions/)•[About](https://towardsdatascience.com/about-towards-data-science-d691af11cc2f/)•[Advertise](https://contact.towardsdatascience.com/advertise-with-towards-data-science)•[Privacy Policy](https://towardsdatascience.com/privacy-policy/)•[Terms of Use](https://towardsdatascience.com/website-terms-of-use/)\n© Insight Media Group, LLC 2026•[The New Stack](https://thenewstack.io)•[roadmap.sh](https://roadmap.sh)•[Creator Network](https://insightmediagroup.io/creator-network)\n####  Recommended Articles \nClose\n  * [ ![](https://h030.towardsdatascience.com/rest/v2/contentStores/d7d3a4ab-7caf-4383-bbd2-fbf7fb4f1787/items/607631/image?etag=1781543525510&width=500&height=500) Critical Mistakes Companies Make When Integrating AI/ML into Their Processes ](https://towardsdatascience.com/critical-mistakes-companies-make-when-integrating-ai-ml-into-their-processes/ \"Critical Mistakes Companies Make When Integrating AI/ML into Their Processes\")\n  * [ ![](https://h030.towardsdatascience.com/rest/v2/contentStores/d7d3a4ab-7caf-4383-bbd2-fbf7fb4f1787/items/607686/image?etag=1782161464448&width=500&height=500) How Relevance Models Foreshadowed Transformers for NLP ](https://towardsdatascience.com/how-relevance-models-foreshadowed-transformers-for-nlp/ \"How Relevance Models Foreshadowed Transformers for NLP\")\n  * [ ![](https://h030.towardsdatascience.com/rest/v2/contentStores/d7d3a4ab-7caf-4383-bbd2-fbf7fb4f1787/items/607639/image?etag=1781250125848&width=500&height=500) Javascript Fatigue: HTMX Is All You Need to Build ChatGPT — Part 1 ](https://towardsdatascience.com/javascript-fatigue-you-dont-need-js-to-build-chatgpt/ \"Javascript Fatigue: HTMX Is All You Need to Build ChatGPT — Part 1\")\n  * [ ![](https://h030.towardsdatascience.com/rest/v2/contentStores/d7d3a4ab-7caf-4383-bbd2-fbf7fb4f1787/items/607930/image?etag=1782124566054&width=500&height=500) The Subset Sum Problem Solved in Linear Time for Dense Enough Inputs ](https://towardsdatascience.com/subset-sum-problem-solved-in-linear-time-for-dense-enough-inputs/ \"The Subset Sum Problem Solved in Linear Time for Dense Enough Inputs\")\n\n\n",
  "metadata": {
    "title": "Local LLM Fine-Tuning on Mac (M1 16GB) | Towards Data Science",
    "description": "Beginner-friendly Python code walkthrough (ft. MLX)",
    "keywords": null,
    "author": "Shaw Talebi",
    "og:locale": "en_US",
    "og:type": "article",
    "og:title": "Local LLM Fine-Tuning on Mac (M1 16GB)",
    "og:description": "Beginner-friendly Python code walkthrough (ft. MLX)",
    "og:url": "https://towardsdatascience.com/local-llm-fine-tuning-on-mac-m1-16gb-f59f4f598be7/",
    "og:site_name": "Towards Data Science",
    "og:image": "https://assets.insightmediagroup.io/media/wp-content/uploads/2024/08/07-r3F1guQD-CUR3v-scaled.jpg",
    "og:image:width": "2560",
    "og:image:height": "1920",
    "og:image:type": "image/jpeg",
    "twitter:card": "summary_large_image",
    "twitter:site": "@TDataScience",
    "twitter:creator": "@TDataScience",
    "twitter:label1": "Written by",
    "twitter:data1": "Shaw Talebi",
    "twitter:label2": "Est. reading time",
    "twitter:data2": "8 min read",
    "article:published_time": "2024-08-01T14:22:13.000Z",
    "article:modified_time": "2024-08-01T14:22:13.000Z",
    "article:author": "https://towardsdatascience.com/author/shawhin/"
  },
  "paywall": {
    "listed_paid": true,
    "detected": false,
    "marker": "",
    "public_only": true,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_000.txt",
      "chars": 55
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_001.txt",
      "chars": 72
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_002.txt",
      "chars": 100
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_003.txt",
      "chars": 95
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_004.txt",
      "chars": 386
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_005.txt",
      "chars": 662
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_006.txt",
      "chars": 198
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_007.txt",
      "chars": 677
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_008.txt",
      "chars": 679
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_009.txt",
      "chars": 476
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_010.txt",
      "chars": 730
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_011.txt",
      "chars": 30
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_012.txt",
      "chars": 267
    },
    {
      "language": "txt",
      "file": "attachments/b964b6337d1d/code/block_013.txt",
      "chars": 182
    }
  ],
  "images": [
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2024/08/07-r3F1guQD-CUR3v-scaled.jpg",
      "alt": "Photo by Myron Mott on Unsplash",
      "local_path": "attachments/b964b6337d1d/images/000.jpg",
      "bytes": 140988,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2020/09/0IPNvWBtK0p96PHMR-scaled.jpg",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/001.jpg",
      "bytes": 571642,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2025/10/image-93.jpg",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/002.jpg",
      "bytes": 400314,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2022/05/00oIEezKoAUE_IvMN-scaled.jpg",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/003.jpg",
      "bytes": 476315,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2020/06/1Irnlz68vLXEApqIhnCPMww.jpeg",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/004.jpeg",
      "bytes": 140475,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2024/09/1tmtCocWuoHpCVd-VZSwh1g.png",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/005.png",
      "bytes": 1826731,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2026/08/fig-a-attention@3x-scaled-1.jpg",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/006.jpg",
      "bytes": 263823,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2023/08/15pzkKDlj_0cuNsIoNOynAw-scaled.jpeg",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/007.jpeg",
      "bytes": 568209,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2020/10/1mlR8YGZAtYSSOwRLVRAXwQ.png",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/008.png",
      "bytes": 1749541,
      "downloaded": true
    },
    {
      "src": "https://assets.insightmediagroup.io/media/wp-content/uploads/2023/08/1EQi-v0WKNCVXDldViCUPvg.png",
      "alt": "",
      "local_path": "attachments/b964b6337d1d/images/009.png",
      "bytes": 24540,
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [
    {
      "src": "https://www.youtube.com/channel/UCa9gErQ9AE5jT2DZLjXBIdA",
      "quality": "unavailable",
      "local_path": "",
      "note": "无1080p且无720p，未交付更低清晰度"
    },
    {
      "src": "https://www.youtube.com/c/TowardsDataScience",
      "quality": "unavailable",
      "local_path": "",
      "note": "无1080p且无720p，未交付更低清晰度"
    }
  ],
  "links": [
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/latest/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/tag/editors-pick/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/tag/the-variable/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/shipai/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/submissions/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/category/artificial-intelligence/large-language-models/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/author/shawhin/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/qlora-how-to-fine-tune-an-llm-on-a-single-gpu-4e44d6b5be32"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/tag/hands-on-tutorials/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/tag/large-language-models/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/tag/llm/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/tag/mac/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/tag/python/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/my-experience-as-a-bertelsmann-tech-and-deep-learning-nanodegree-graduate-459ab27db477/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/category/artificial-intelligence/deep-learning/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/author/mrakelinggar/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/how-to-perform-effective-agentic-context-engineering/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/author/oieivind/"
    },
    {
      "type": "internal",
      "href": "https://towardsdatascience.com/how-to-read-multiple-csv-files-non-iteratively-and-without-pandas-984fd954999c/"
    },
    {
      "type": "external",
      "href": "https://write.insightmediagroup.io"
    },
    {
      "type": "external",
      "href": "https://www.linkedin.com/company/towards-data-science/"
    },
    {
      "type": "external",
      "href": "https://x.com/TDataScience"
    },
    {
      "type": "external",
      "href": "https://shawhin.medium.com/list/large-language-models-llms-8e009ae3054c"
    },
    {
      "type": "external",
      "href": "https://unsplash.com/@s2killa"
    },
    {
      "type": "external",
      "href": "https://unsplash.com"
    },
    {
      "type": "external",
      "href": "https://roadmap.sh/ai-engineer"
    },
    {
      "type": "external",
      "href": "https://ml-explore.github.io/mlx/build/html/index.html"
    },
    {
      "type": "external",
      "href": "https://github.com/ml-explore/mlx-examples/tree/main/lora"
    },
    {
      "type": "external",
      "href": "https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx"
    },
    {
      "type": "external",
      "href": "https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx/data"
    },
    {
      "type": "external",
      "href": "https://huggingface.co/mlx-community/Mistral-7B-Instruct-v0.2-4bit"
    },
    {
      "type": "external",
      "href": "https://huggingface.co/mlx-community"
    },
    {
      "type": "external",
      "href": "https://github.com/ShawhinT/YouTube-Blog/blob/main/LLMs/qlora-mlx/scripts/convert.py"
    },
    {
      "type": "external",
      "href": "https://github.com/ShawhinT/YouTube-Blog/blob/main/LLMs/qlora-mlx/data/prep-data.ipynb"
    },
    {
      "type": "external",
      "href": "https://github.com/ml-explore/mlx-examples/blob/main/lora/lora.py"
    },
    {
      "type": "external",
      "href": "https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/qlora-mlx/scripts"
    },
    {
      "type": "external",
      "href": "https://shawhin.medium.com/list/8e009ae3054c"
    },
    {
      "type": "external",
      "href": "https://shawhintalebi.com/"
    },
    {
      "type": "external",
      "href": "https://calendly.com/shawhintalebi"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T11:11:49Z",
  "source_url": "https://towardsdatascience.com/local-llm-fine-tuning-on-mac-m1-16gb-f59f4f598be7/",
  "delivery_status": "excluded_paid",
  "discovery_status": "excluded_paid",
  "missing_reason": "按原约定排除付费/会员全文"
}