About Garrit Franke

a generalist DevOps Engineer

The RSS's url is : https://garrit.xyz/rss.xml

Please copy to your reader or subscribe it with :

Preview of RSS feed of Garrit Franke

Installing MSSQL Client Drivers for a PHP Application

2024-09-24 08:00:00

I just had the pleasure (cough) to connect an MSSQL database to a Laravel application at work. Because the process was super tedious, I wanted to quickly jot this down so I will never have to go through this again.

Our setup

We're building a Laravel application with DDEV. DDEV essentially moves all development tools into Docker containers and adds some nice features like local database management.

The process

Laravel comes with the boilerplate to use MSSQL out of the box. In your app, just set the database config to use sqlsrv:

php 'connections' => [ 'sqlsrv' => [ 'driver' => 'sqlsrv', 'url' => env('DB_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '1433'), 'database' => env('DB_DATABASE', 'laravel'), 'username' => env('DB_USERNAME', 'root'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => env('DB_CHARSET', 'utf8'), 'prefix' => '', 'prefix_indexes' => true, // 'encrypt' => env('DB_ENCRYPT', 'yes'), // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), ], ],

You will see errors when starting your app, because you need to install the corresponding drivers first. Instead of adding them through Composer (a widely adopted package manager for PHP), you have to install the ODBC drivers through the system package manager, because Microsoft doesn't maintain a PHP package. Furthermore, you also have to install the driver repository because Microsoft doesn't even maintain packages for the major Linux distributions. In our setup with DDEV, this has to be done by amending the Dockerfile used for the application container. Create a file at .ddev/web-build/Dockerfile and add the following contents:

`dockerfile

https://ddev.readthedocs.io/en/stable/users/extend/customizing-images/#adding-extra-dockerfiles-for-webimage-and-dbimage

https://stackoverflow.com/questions/58086933/how-to-install-the-sql-server-php-drivers-in-ddev-local#new-answer

ARG BASEIMAGE FROM $BASEIMAGE

RUN npm install --global forever RUN echo "Built on $(date)" > /build-date.txt

RUN curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -

RUN curl https://packages.microsoft.com/config/debian/11/prod.list > /etc/apt/sources.list.d/mssql-release.list

RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg RUN curl https://packages.microsoft.com/config/debian/12/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list

RUN apt-get update RUN apt-get --allow-downgrades -y install libssl-dev RUN apt-get -y update && yes | ACCEPTEULA=Y apt-get -y install php8.3-dev php-pear unixodbc-dev htop RUN ACCEPTEULA=Y apt-get -y install msodbcsql18 mssql-tools18 RUN sudo pecl channel-update pecl.php.net RUN sudo pecl install sqlsrv RUN sudo pecl install pdo_sqlsrv

RUN sudo printf "; priority=20\nextension=sqlsrv.so\n" > /etc/php/8.3/mods-available/sqlsrv.ini RUN sudo printf "; priority=30\nextension=pdosqlsrv.so\n" > /etc/php/8.3/mods-available/pdosqlsrv.ini RUN sudo phpenmod -v 8.3 -s cli sqlsrv pdosqlsrv RUN sudo phpenmod -v 8.3 -s fpm sqlsrv pdosqlsrv RUN sudo phpenmod -v 8.3 -s apache2 sqlsrv pdo_sqlsrv

RUN sudo printf "; priority=20\nextension=sqlsrv.so\n" > /etc/php/8.3/mods-available/sqlsrv.ini RUN sudo printf "; priority=30\nextension=pdosqlsrv.so\n" > /etc/php/8.3/mods-available/pdosqlsrv.ini RUN sudo phpenmod -v 8.3 -s cli sqlsrv pdosqlsrv RUN sudo phpenmod -v 8.3 -s fpm sqlsrv pdosqlsrv RUN sudo phpenmod -v 8.3 -s apache2 sqlsrv pdo_sqlsrv

RUN echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile `

If you're reading this in the future and Microsoft may have released a new version of the ODBC drivers, you may have to follow the new installation instructions from their documentation. It took me a while to realize that I couldn't install version 17 of the driver because I was using the installation instructions for version 18. They are apparently incompatible with each other.

I hope that you'll never have to touch the shithole that is MSSQL, but if you do, I hope that this guide will be of value to you.

Mental AI Fog and how to cure it

2024-09-01 08:00:00

The term "AI Slop" is currently on the rise. It describes all the AI generated images and texts we see on the internet. I'd like to propose a term that basically describes reverse AI Slop: Mental AI Fog.

Instead of consuming too much AI generated content (which also applies), AI Fog describes the inability to produce content without the help of AI. We're surrounded by flowery written articles and resources that we think that it's not worth it to put in the effort to write a text ourselves. This is comparable to how computer keyboards, spellchecking and autocorrection have rendered my generation and the ones to come incapable of comfortably writing longform text.

I'm currently strongly suffering from AI fog. I'm so used to letting some LLM flesh out a quick and dirty prompt nowadays that it's hard for me to write this text, get the point across and not feel insecure about my style of writing. This site is supposed to be a way to persist my thoughts whenever I want to, but are they still my thoughts if they have been proofread and corrected by a computer?

As a result, all these thoughts are piling up in my head. Where I previously braindumped thoughts on a piece of paper, I now only come up with a couple of words and let the AI elaborate. I'm consuming what are supposed to be my own thoughts, which perpetuates the cycle.

This needs to stop. I need to get back creating things myself. I decided to abandon the use of LLMs for most content on this site. And where AI has been used, it will be clearly mentioned. I'm contemplating adding some sort of "Backed by AI" label for certain pages to make it harder for myself to fall back to a helping hand. I will likely still be using LLMs, but making it obvious will force me to mindfully choose where it will be used.

Is this something you can relate to? Is AI fog even a fitting term for this? I don't know. And if it isn't, that's okay because I came up with it myself.

Sentiment analysis using ML models

2024-08-31 08:00:00

I just rewrote parts of my Positive Hacker News RSS Feed project to use an ML model to filter out any negative news from the Hacker News timeline. This method is far more reliable than the previous method of using a rule-based sentiment analyzer through NLTK.

I'm using the model cardiffnlp/twitter-roberta-base-sentiment-latest, which was trained on a huge amount of tweets. It's really tiny (~500 MB) and easily runs inside the existing GitHub Actions workflows. You can try out the model yourself on the HuggingFace model card.

<img width="522" alt="grafik" src="https://github.com/user-attachments/assets/06f42df6-624a-4108-ada8-d0d37a53e693">

If you want to subscribe to more positive tech news, simply replace your Hacker News feed of your RSS reader with this one (or add it if you haven't already): https://garritfra.github.io/positive_hackernews/feed.xml

How embedding models encode semantic meaning

2024-08-03 08:00:00

Embedding models have long been a daunting concept for me. But what are they? And why are they so useful? Let's break it down in simple terms.

What's an embedding?

An embedding is basically a numerical representation of a piece of information - it could be text, audio, an image, or even a video. Think of it as a way to capture the essence or meaning of that information in a list of numbers.

For example, let's say we have this text: "show me a list of ground transportation at boston airport". An embedding model might turn that into something like this:

[0.03793335, -0.008010864, -0.002319336, -0.0110321045, -0.019882202, -0.023864746, 0.011428833, -0.030349731, -0.044830322, 0.028289795, -0.02810669, -0.0032749176, -0.04208374, -0.0077705383, -0.0033798218, -0.06335449, ... ]

At first, thus looks like a jumble of numbers. But each of these numbers points to a specific area within the embedding model's "space", where similar words or concepts might be located.

Visualizing embeddings

To help wrap our heads around this, let's look at a visualization. This beautiful image shows the entirety of the nomic-embed-text-v1.5 embedding model, as generated by this visualization tool:

nomic-embed-text-v1.5-full

Now, if we take our example text about Boston airport transportation and plot its embeddings on this map, we'd see that some clusters are lit up, especially around "transportation". This means that the model has figured out that the topic of the query must be related to transportation in some way.

nomic-embed-text-v1.5-query

Zooming into this image, we can see more specific topics around transportation, like "Airport", "Travel" or "Highways" are lit up, which more closely matches our query.

nomic-embed-text-v1.5-transportation

In a nutshell, embedding models are able to group terms by topics that are related to each other.

Why should we care about embeddings?

Encoding meaning in text has tons of different use cases. One that I'm particularly excited about is building RAG applications. RAG stands for Retrieval-Augmented Generation and refers to a method for Large Language Models (LLMs), where, given a question, you enrich the original question with relevant bits of information before answering it.

Here's how embeddings are useful for RAG:

  1. You have a bunch of documents in your data source.
  2. You use an embedding model to turn each document into a list of numbers (like we saw earlier).
  3. When someone asks a question, you also turn that question into a list of numbers.
  4. Then, you find the documents whose number lists are most similar to your question's number list.
  5. Voila! You've found the most relevant documents to answer the question.

This method is way better than previously used techniques like just searching for exact words in the documents. It's like the difference between having a librarian who only looks at book titles, and one who actually understands what the books are about.

Other things you can do with embeddings

Beyond RAG applications, embeddings are super useful for all sorts of things:

  1. Smarter searches: Find related stuff even if the exact words don't match.
  2. Better recommendations: "You liked this? You might also like these similar things!"
  3. Language translation: Help computers understand that "dog" in English and "perro" in Spanish mean the same thing.
  4. Sentiment analysis: Figure out if someone's happy or grumpy based on their tweet.

Wrapping it up

Embeddings are a clever way to turn words (or images, or sounds) into numbers that computers can understand and compare. By doing this, we can make emerging AI technologies a whole lot smarter at understanding language and finding connections between ideas.

Next time you're chatting with an AI or getting scarily accurate recommendations online, you can nod knowingly and think, "Ah yes, embeddings at work!"

πŸ”— Linkdump: LLMs

2024-07-02 08:00:00

The more I'm getting into large language models (LLMs), the more I'm fascinated about what you can do with them. To "digest" my reading list of cool articles and projects regarding LLMs, I assembled the following list. If you're also interested but haven't started your journey into this neverending rabbit hole, these may contain some good pointers:

Running LLMs

Building Chatbots & Applications

Training and finetuning

Miscellaneous projects

Blogs

Testing SMTP connections

2024-06-27 08:00:00

Just a quick note to my future self on how to test a SMTP connection with nothing but a tiny busybox container.

In my case specifically, I tested the connection from inside a Kubernetes cluster. Here's the quickest way to get a temporary pod up and running:

kubectl run -n backend -i --tty --rm debug --image=busybox --restart=Never

Busybox comes with telnet installed, which we can use to establish a connection to the server:

/ # telnet smtp.mydomain.com 25 Connected to smtp.mydomain.com 220 mail.mydomain.com ESMTP Postfix (SMTP)

Next, we can issue the SMTP commands through the open TCP connection to send a test mail. Lines beginning with a status code are server responses:

` HELO smtp.mydomain.com 250 smtp.mydomain.com MAIL FROM:[email protected]
250 2.1.0 Ok RCPT TO:[email protected] 250 2.1.5 Ok DATA
354 End data with <CR><LF>.<CR><LF> From: [noreply] [email protected] To: [Receiver] [email protected] Date: Thu, 27 Jun 2024 10:08:26 -0200 Subject: Test Message

This is a test message.

. 250 2.0.0 Ok: queued as 2478B7F135 `

In case there's a firewall issue, you might not be able to establish a connection in the first place, or you won't get a reply to your TCP commands. In our case, everything worked fine.

I hope this is useful!

Host your own LLM

2024-06-17 08:00:00

I'm currently dipping my toes into Large Language Models (LLMs, or "AI") and what you can do with them. It's a fascinating topic, so expect some more posts on this in the coming days and weeks.

For starters, I wanted to document how I got my first LLM running on my local machine (a 2022 MacBook Pro). Ollama makes this process super easy. You just install it (brew install ollama in my case) and then run the model:

ollama run llama3

This will download the model and open a prompt, so you can start chatting right away!

You can think of Ollama as the Docker CLI but for LLMs. There's a directory of LLMs, and if a model has multiple different sizes, you can use it like you would pull a different docker tag:

ollama pull llama3:8b ollama pull llama3:70b

The best thing about ollama is that it also exposes a web server for you to integrate the LLM into your application. As an example, here's how you would curl your local LLM:

curl http://localhost:11434/api/chat -d '{ "model": "llama3", "messages": [{ "role": "user", "content": "Are you a robot?" }], "stream": false }' {"model":"llama3","created_at":"2024-06-17T11:19:23.510588Z","message":{"role":"assistant","content":"I am not a human, but I'm also not a traditional robot. I'm an artificial intelligence language model designed to simulate conversation and answer questions to the best of my ability. My \"brain\" is a complex algorithm that processes natural language inputs and generates responses based on patterns and associations learned from large datasets.\n\nWhile I don't have a physical body or consciousness like humans do, I'm designed to interact with humans in a way that feels natural and conversational. I can understand and respond to questions, make suggestions, and even tell jokes (though my humor may be a bit... algorithmic).\n\nSo, while I'm not a human or a traditional robot, I exist at the intersection of technology and language, designed to assist and communicate with humans in a helpful way!"},"done_reason":"stop","done":true,"total_duration":12565842250,"load_duration":7059262291,"prompt_eval_count":15,"prompt_eval_duration":331275000,"eval_count":156,"eval_duration":5172858000}

If your local machine is not beefy enough and you want to try out a large LLM on a rented server (AWS has g5.2xlarge, which gave me good results for mixtral 8x7b), you also have to set OLLAMA_HOST=0.0.0.0 in your environment variables to be able to reach the remote server. This exposes the LLM to the public internet, so be careful when chosing your deployment strategy.

And there you go! You just deployed your very own LLM. Pretty cool, huh?

I just cleaned up 40 GB of Brew caches

2024-06-03 08:00:00

EDIT: This trick will probably not be as effective on your system as it was on my system. After writing this post I realized that I had the HOMEBREW_NO_INSTALL_CLEANUP=1 flag enabled on my system.

My system (MacOS) is getting more cluttered the more I use it. I'm sure you can relate. If you're using Brew as your package manager (which you should πŸ˜‰), you might want to consider running the following command:

brew cleanup -s

For some reason this failed after some time with a "directory not found" error, but you can just run it again and it will continue cleaning up old caches. Once it was done, this freed up 40 GB of disk space on my system. It might make sense to run this as a cronjob? Either way, I just wanted to jot this down before I enevitably forget this, as usual.

Going from self hosted to managed software

2024-05-24 08:00:00

Some time ago I was heavily into self hosting my own software. Over time though, it became apparent that maintaining these services is a huge burden. I either abandoned most of the services or found a replacement that suits my needs and saves me time that's better spent on other things in life.

Today, I finally pulled the plug on Miniflux, the last service I used to self host (not counting House Assistant on a Pi, which I use to automate some stuff at home). The Hetzner server it ran on cost me ~4€ a month. The maintainer of Miniflux offers a managed hosting solution for 15$ a year, so to save money and time, and to support the project, I decided to switch from self-hosted to managed.

Will I ever self host again?

I really don't know. Some services (Miniflux included) required very little maintenance to keep running, so I could see myself spinning up a server again if I really wanted to run some software that doesn't have managed hosting. For now though, I'm planning on using managed services wherever I can. Nevertheless I'm proud of the things I learned during my time of self hosting my software. I think it gave me a huge boost both in terms of know how and my career, and I'd encourage everyone to dip a toe into self hosting.

About my 'smart' G-Shock

2024-05-10 08:00:00

About two weeks ago, I got myself my very first G-Shock. My entry ticket to the #CasioCult! Since I didn't want to miss out on any fitness features, I went with the G-Shock GW-H5600, which comes with heart rate monitoring, step tracking and some other nice to have features.

A G-Shock DW-H5600

Having read every review I could find, I knew that the watch had some quirks, but I ultimately loved the look of it. But two weeks later, I'm forced to return the watch. Let me first go over what I liked and dislike about this watch.

Pros

It's a G-Shock

I love the look and feel of a G-Shock and other Casio watches. This is my first G-Shock, but I've had an eye on this brand for quite some time. It's tough, sturdy, waterproof and probably also bullet proof.

The display

Oh, the display! It's gorgeous. Many people are complaining why this MIP display hasn't found its way to the rest of the G-Shock lineup. But I'm sure they will retrofit other models soon.

Proper paper manual

My first impression after the unboxing was "holy sheers, the manual is a book"! And I mean that in the best way possible. Every little feature of the watch is explained in extreme detail in the manual. You rarely see this in other watches or gadgets these days.

Cons

Questionable UI and UX decisions

G-Shocks are known for user interfaces that "just work". In this watch however, there are a few things that really make the watch frustrating to operate. Just to name a few quirks:

A bit thick

Below the already thick bezel of the G-Shock sits the heart rate monitor, which is obnoxiously huge. I personally didn't feel like it irritated my skin, but it does add to the thickness.

Fitness Features

This is a two-edged sword. I originally wanted to list this as a pro. Features like run tracking, cardio status and sleep analysis are there, and they work fine. The step tracking and heart rate monitoring can be a bit off from time to time, but it's fine for the occasional run.

What's really bothering me is the mediocre implementation. There's no workout detection, the autopause feature barely works and you're limited to running, walking, gym workout and interval training. I also want to log my bike rides, which will always show up as a running activity in my app.

They recently added Strava integration, which sort of works. The data is all there, but for some reason the pace and moving time that Strava computes are completely off. For example, I ran 55 minutes straight with an average pace of 9 minutes / km. But with the data the watch sends, Strava thinks I only moved for 26 minutes with a pace of 4 minutes / km. If that were true, I could compete in the olympics! πŸ˜…

Notifications barely work

During the time I owned the watch, there was only one random day where the watch received notifications from my phone. I can't explain why, but I just didn't get this to work properly.

Case is not screwed in. Could fall off

This is just a minor thing if you really care about durability. All G-Shock squares so far had screwed in bezels. On this model, you can pull off the bezel with enough force. I've never done it, but losing the bezel might be a concern.

What's next?

I enjoyed my time with this watch, but I filed a return. As pretty as the watch is, it is just too frustrating to use. Smart watches aren't a core part of Casio's business, and you can feel that in the lack of quality of the software. The app was likely developed as a one-off contract by some random agency, and once the contract ends, the watch won't ever be improved again.

I've now ordered the Garmin Instinct 2S Solar, which is very similar in terms of specs. MIP display, top-up solar charging, long-lasting battery and fitness features. But on top of that, it has features like music control, GPS, contactless payment and a compass. Contrary to Casio, Smartwatches are a core part of Garmin's business, which makes me believe that they go out of their way to develop the best possible watch they can. I will likely follow up with how this new watch compares to my G-Shock.