Dockerfile für SNIPS NLU – Fix für SSLError / CertificateError

Trotz generativer KI ist das Thema NLU noch nicht ganz vom Tisch. Dem ein oder anderen ist die SNIPS NLU vermutlich noch ein begriff. Diese leichtgewichtige NLU wurde seinerzeit als Open-Source NLU umgesetzt und zeichnete sich durch seine Offlinefähigkeit aus. Nachdem das Startup hinter der NLU von Sonos übernommen wurde war dann Schluß mit Lustig für die NLU. Zwar steht das Repository noch auf Github zur Verfügung, lässt sich aber nicht mehr ohne weiteres bauen oder installieren.

Da ich die NLU selbst für ein eigenes Projekt benötige habe ich mir die Mühe gemacht, selbige wieder zum Laufen zu bekommen. Die hierfür notwendigen Schritte sind in diesem Artikel dokumentiert.

Was ist das Fehlerbild?

Versucht man die SNIPS-NLU wie in der Dokumentation beschrieben zu installieren so kommt es zu einem SSL-Fehler. Der Fehler selbst tritt beim Versuch die Entitys für Deutsch herunterzuladen. Hierbei kommt die folgende Fehlermeldung:

requests.exceptions.SSLError: HTTPSConnectionPool(host='resources.snips.ai', port=443): Max retries exceeded with url: /nlu/gazetteer-entities/de/country/v0.2/latest (Caused b
y SSLError(CertificateError("hostname 'resources.snips.ai' doesn't match either of 'cloudfront.net', '*.cloudfront.net'",),))

Die Fehlermeldung ist recht eindeutig und sagt aus, dass das SSL-Zertifikat für die Domain resources.snips.ai quasi abgelaufen ist und aus diesem Grund der SSL-Check fehlschlägt. Der Download der System-Entities ist somit leider nicht möglich.

utils.py bearbeiten und SSL-Check deaktivieren

Nachdem meine Versuche fehlschlugen den SSL-Check auf Betriebssystemebene zu deaktivieren blieb mir nur ein Blick in den Quellcode. Die SNIPS NLU lädt über die Datei utils.py über eine Methode ‘get_json’ das Json-File vom Remote Server. Hierbei wird die requests.get Methode genutzt. Über die zusätzliche Angabe des Parameters ‘verify=False’ kann die SSL-Zertifikatsprüfung deaktiviert werden.

alter Code (ab Zeile 71)
def get_json(url, desc):
    r = requests.get(url)
    if r.status_code != 200:
        raise OSError("%s: Received status code %s when fetching the resource"
                      % (desc, r.status_code))
    return r.json()
neuer Code – siehe Github
def get_json(url, desc):
    r = requests.get(url, verify=False)
    if r.status_code != 200:
        raise OSError("%s: Received status code %s when fetching the resource"
                      % (desc, r.status_code))
    return r.json()

Docker-Image bauen und Files ersetzen

Nachdem nun die entsprechenden Anpassungen im Code erfolgt sind muss noch der passende Docker-Container gebaut werden. Hier mein Docker-File:

FROM python:3.6-slim-stretch

#set TimeZone
ENV TZ="Europe/Berlin"

#setup Snips
RUN pip install urllib3==1.26.6
RUN pip install snips-nlu

#Download Languages
RUN python -m snips_nlu download-all-languages

#Copy Files for Snips
COPY files/cli/utils.py /usr/local/lib/python3.6/site-packages/snips_nlu/cli/utils.py

#Prepare for Downloading languages
RUN pip config set global.trusted-host "resources.snips.ai" --trusted-host=https://resources.snips.ai/

#Download entites
RUN python -m snips_nlu download-language-entities de
RUN python -m snips_nlu download-language-entities en

#setup Endpoints
RUN pip install fastapi
RUN pip install uvicorn

SNIPS NLU Code auf Gihub veröffentlicht

Sowohl der Code der angepassten utils.py als auch des Dockerfiles wurden auf Github.com veröffentlicht:

Erweiterung im Webservice

Im Dockerfile selbst wird von mir noch die fastapi mit installiert. Dies hat den Hintergrund dass ich mir einen eigenen kleinen Restservice mit Python geschrieben habe, welcher mit die Snips-Funktionalitäten per Rest bereit stellt. So kann die NLU bequem in bestehende Prozesse integriert werden.

Sollte jemand Interesse an diesem Service haben so gebt mir kurz bescheid und ich veröffentlichte den aktuellen Code. Dieser ist aktuell noch in Arbeit, so dass eine Veröffentlichung aktuell noch wenig Sinn ergibt 🙂

Artikel teilen

This article was written by Thomas Schiffler

Alles was mit IT zu tun hat steht bei mir hoch im Kurs. Hierbei dreht sich vieles um Java, Python oder auch mal PHP. Unser Zuhause ist mit diversen Raspberry PIs ausgestattet mit welchen ich versuche unser Leben durch etwas Automatisierung ein wenig smarter zu gestalten. Hierbei möchte ich die Technik und die dahinter eingesetzten Tools / Frameworks verstehen und nicht einfach nur Anwenden. Ich selbst bezeichne mich als ITler aus Leidenschaft :) Seit 2020 ist das Thema Chatbot / Voicebot / Conversational.ai in meinen Focus gerückt. In diesem Bereich investiere ich gerade viel Zeit.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert