Seite 1 von 1

Flask App Datenbankabfrage

Verfasst: Dienstag 10. Mai 2022, 08:23
von MaybeR6x
Guten Tag zusammen,

ich hoffe ich kann mein Problem gut beschreiben und jemand hat eine Antwort und am besten eine Lösung.

Ich habe eine Flask App (app.py) die beim Aufruf
@app.post("/predict")
def predict():
text = request.get_json().get('message')
response = get_response(text)
usw.

die Methode get_response() Aufruft und in der Methode wird eine Datenbankabfrage gemacht.
Jetzt habe ich gemerkt das wenn ich die Flask App gestartet habe und sich Datensätze in der Datenbank ändern, diese nicht Aktualisiert über get_response() ausgegeben werden.
Erst wenn ich den Server/die App neu starte.

Gibt es hierfür eine Lösung? oder ist das grunsätzlich nicht anders möglich?

Re: Flask App Datenbankabfrage

Verfasst: Dienstag 10. Mai 2022, 08:39
von __deets__
Da es ja nun viele Anwendungen gibt, bei denen das klappt, geht das grundsätzlich.

Du zeigst den relevanten Teil deiner Datenbankabfrage nicht, denn das hat damit zu tun. Nix mit flask, das hat auf die keinen Einfluss. Datenbanken haben üblicherweise Transaktionen, die sie voneinander isolieren. Damit musst du umgehen, wie genau, hängt vom Code und anwedungszweck ab.

Re: Flask App Datenbankabfrage

Verfasst: Dienstag 10. Mai 2022, 08:51
von MaybeR6x
__deets__ hat geschrieben: Dienstag 10. Mai 2022, 08:39 Da es ja nun viele Anwendungen gibt, bei denen das klappt, geht das grundsätzlich.

Du zeigst den relevanten Teil deiner Datenbankabfrage nicht, denn das hat damit zu tun. Nix mit flask, das hat auf die keinen Einfluss. Datenbanken haben üblicherweise Transaktionen, die sie voneinander isolieren. Damit musst du umgehen, wie genau, hängt vom Code und anwedungszweck ab.
Im grunde ist das die Datenbank Abfrage um die es geht:
mycursor.execute(f"SELECT Path FROM nltk_model where Active = 1 AND Kunden_NR = {kunde}")
path = mycursor.fetchall()
data = torch.load(str(path[0][0]))


die ganze methode sieht wie folgt aus:

def get_response(msg,kunde,chatID):
sql = "INSERT INTO messages (msg_id, msg,sent_by,Kunden_NR) VALUES (%s, %s, %s, %s)"
val = (chatID, msg,"User",kunde)
mycursor.execute(sql, val)
mydb.commit()

mycursor.execute(f"SELECT Path FROM nltk_model where Active = 1 AND Kunden_NR = {kunde}")
path = mycursor.fetchall()
data = torch.load(str(path[0][0]))
doc = getEntitys(msg,kunde)
doc = "Entities", [(ent.text, ent.label_) for ent in doc.ents]
input_size = data["input_size"]
hidden_size = data["hidden_size"]
output_size = data["output_size"]
all_words = data['all_words']
tags = data['tags']
model_state = data["model_state"]
model = NeuralNet(input_size, hidden_size, output_size).to(device)
model.load_state_dict(model_state)
model.eval()

mycursor.execute(f"SELECT tag FROM intents where active = 1 AND Kunden_NR = {kunde}")
tag = mycursor.fetchall()
jsonData = '{"intents": ['
for x in tag:
jsonData += '{' + f'"tag": "{x[0]}","patterns": ['
mycursor.execute(f"SELECT pattern FROM patterns where tag = '{x[0]}' AND Kunden_NR = {kunde}")
patterns = mycursor.fetchall()
for y in patterns:
jsonData += f'"{y[0]}",'
jsonData = jsonData[:-1]
jsonData += '],"responses": ['
mycursor.execute(f"SELECT responses FROM responses where tag = '{x[0]}' AND Kunden_NR = {kunde}")
patterns = mycursor.fetchall()
for y in patterns:
jsonData += f'"{y[0]}",'
jsonData = jsonData[:-1]
jsonData += ']},'
jsonData = jsonData[:-1] + "]}"
intents = json.loads(jsonData)

sentence = tokenize(msg)
X = bag_of_words(sentence, all_words)
X = X.reshape(1, X.shape[0])
X = torch.from_numpy(X).to(device)

output = model(X)
_, predicted = torch.max(output, dim=1)

tag = tags[predicted.item()]

probs = torch.softmax(output, dim=1)
prob = probs[0][predicted.item()]
if prob.item() > 0.75:
for intent in intents['intents']:
if tag == intent["tag"]:
answer = random.choice(intent['responses']) + str(doc)
sql = "INSERT INTO messages (msg_id, msg,sent_by,Kunden_NR) VALUES (%s, %s, %s, %s)"
val = (chatID, answer,"Bot",kunde)
mycursor.execute(sql, val)
mydb.commit()

return answer
answer = "I do not understand..." + str(doc)
sql = "INSERT INTO messages (msg_id, msg,sent_by,Kunden_NR) VALUES (%s, %s, %s, %s)"
val = (chatID, answer,"Bot",kunde)
mycursor.execute(sql, val)
mydb.commit()
return answer

Re: Flask App Datenbankabfrage

Verfasst: Dienstag 10. Mai 2022, 09:27
von __deets__
Bitte in Zukunft die Code-Tags benutzen, wenn du hier Code postest, damit die Einrueckungen erhalten bleiben.

Da sind eine Menge Probleme drin. Der groesste Klopper: die Eingabe "kunde" wird einfach mittels eines Formatstrings in eine SQL-Abfrage geballert. Und kann da beliebigen Schaden anrichten. Du musst *ueberall* die parametrisierte Form von execute verwenden, was du komischerweise an anderer Stelle auch machst.

JSON baut man nicht per String-Operationen zusammen, sondern nutzt json.dumps, um aus einer Datenstruktur eine JSON-Repraesentation zu bekommen. Und eigentlich noch nicht mal das, die Datenstruktur sollte Flask selbst in JSON umwandeln koennen. Und die Mischung aus + und format-strings ist auch "ungewoehnlich".

Viel zu lang und unuebersichtlich ist das Ding dann auch noch geworden.

mydb/mycursor fallen vom Himmel. Das ist mein Kandidat 1 fuer das von dir beobachtete Verhalten. Ich wuerde da ein funktionierendes Beispiel aus der Dokumentation von was auch immer du als DB-Adapter benutzt zugrunde legen, und dich dann langsam dahinarbeiten.

Re: Flask App Datenbankabfrage

Verfasst: Dienstag 10. Mai 2022, 11:30
von Sirius3
@__deets__: es ist ja noch schlimmer, der JSON-String wird nicht für die Rückgabe generiert, sondern um dann per json.loads die Daten in Python zu lesen!

@MaybeR6x: Warum liest Du die `intents` zu allen `tags`, obwohl Du nur ein einziges davon brauchst?
`doc` ist kein Objekt, das man sinnvoll in einen String umwandeln kann. Sowas will der Nutzer doch nicht sehen.

Die lange Funktion muß in viele kleine Funktionen aufgespalten werden. Es darf keine globalen Variablen geben.
Variablennamen schreibt man klein. Benutze keine Abkürzungen.
`cursor` sind was kurzlebiges und werden nicht herumgereicht.

Insgesamt komm ich bei sowas raus (ungetestet):

Code: Alles auswählen

def read_intent(database, kunde, tag):
    with closing(database.cursor()) as cursor:
        cursor.execute(f"SELECT count(*) FROM intents where active = 1 AND tag = %s AND Kunden_NR = %s", [tag, kunde])
        count = cursor.fetchone()[0]
        if count == 0:
            return None
        cursor.execute(f"SELECT pattern FROM patterns where tag = %s AND Kunden_NR = %s", [tag, kunde])
        patterns = [p for p, in cursor]
        cursor.execute(f"SELECT responses FROM responses where tag = %s AND Kunden_NR = %s", [tag, kunde])
        responses = [r for r, in cursor]
        return patterns, response

def write_message(database, chat_id, message, sent_by, kunde):
    with closing(database.cursor()) as cursor:
        sql = "INSERT INTO messages (msg_id, msg,sent_by,Kunden_NR) VALUES (%s, %s, %s, %s)"
        cursor.execute(sql, [chat_id, message, sent_by, kunde])
    database.commit()

def predict(database, kunde, message):
    with closing(database.cursor()) as cursor:
        cursor.execute(f"SELECT Path FROM nltk_model where Active = 1 AND Kunden_NR = %s", [kunde])
        path = cursor.fetchone()[0]
    
    data = torch.load(path)
    input_size = data["input_size"]
    hidden_size = data["hidden_size"]
    output_size = data["output_size"]
    all_words = data['all_words']
    tags = data['tags']
    model_state = data["model_state"]
    model = NeuralNet(input_size, hidden_size, output_size).to(device)
    model.load_state_dict(model_state)
    model.eval()

    sentence = tokenize(message)
    X = bag_of_words(sentence, all_words)
    X = X.reshape(1, X.shape[0])
    X = torch.from_numpy(X).to(device)

    output = model(X)
    _, predicted = torch.max(output, dim=1)

    tag = tags[predicted.item()]

    probs = torch.softmax(output, dim=1)
    prob = probs[0][predicted.item()]
    return tag, prob

def get_response(database, message, kunde, chat_id):
    write_message(database, char_id, message, "User", kunde)

    doc = get_entitys(database, message, kunde)
    doc = "Entities", [(ent.text, ent.label_) for ent in doc.ents]

    tag, prob = predict(database, kunde)

    intent = read_intent(database, kunde, tag) if prob.item() > 0.75 else None
    if intent is not None:
        answer = random.choice(intent['responses']) + str(doc)
    else:
        answer = f"I do not understand... {doc}"
    write_message(database, char_id, answer, "Bot", kunde)
    return answer