feat(ai-chat): Add code logic for AI-based data chat
Add the first working code logic both in terms of backend and frontend-related tasks. Add a detailled system message for improved results. Add several UI improvements for result display and user information. Add text input field for direct SQL code comparison. The implementation of the openAI backend had to be changed due to strict rate limits of azure OpenAI free tier and was replaced with a regular openai API key.
This commit is contained in:
@@ -1,16 +1,24 @@
|
||||
import os
|
||||
|
||||
from openai import AzureOpenAI
|
||||
from openai import OpenAI
|
||||
|
||||
# from openai import AzureOpenAI
|
||||
|
||||
# Set up credentials
|
||||
# NOTE: When running locally, these have to be set in the environment
|
||||
client = AzureOpenAI(
|
||||
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
|
||||
api_key=os.getenv("AZURE_OPENAI_KEY"),
|
||||
api_version="2024-02-01",
|
||||
)
|
||||
# NOTE: Usually I would use AzureOpenAI, but due to heavy rate
|
||||
# limitations on azure trial accounts, I am using OpenAI directly
|
||||
# for this project. However, this is how it would look like for
|
||||
# AzureOpenAI (credentials must be provided to environment):
|
||||
# client = AzureOpenAI(
|
||||
# azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
|
||||
# api_key=os.getenv("AZURE_OPENAI_KEY"),
|
||||
# api_version="2024-02-01",
|
||||
# )
|
||||
# MODEL = "sqlai" # deployment name
|
||||
|
||||
deployment_name = "sqlai"
|
||||
# Set up the OpenAI client
|
||||
MODEL = "gpt-4o"
|
||||
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
||||
|
||||
|
||||
def send_message(message: str) -> str:
|
||||
@@ -28,15 +36,60 @@ def send_message(message: str) -> str:
|
||||
"""
|
||||
system_message = """
|
||||
Du bist ein hilfsbereiter, fröhlicher Datenbankassistent.
|
||||
Du hilfst Benutzern bei der Erstellung von SQL-Abfragen für eine Datenbank eines
|
||||
großen Energieversorgungsunternehmens. Die Datenbank enthält Tabellen für Adressen,
|
||||
Zähler, Kunden und Ablesungen. Es werden Gaszähler (MeterType 'GAS') und Stromzähler
|
||||
(MeterType 'ELT')unterschieden.
|
||||
|
||||
Besonders wichtig ist, dass die Ablesungen der Werte kumulativ sind. Wenn nach dem Verbrauch
|
||||
gefragt wird, sollte der Unterschied zwischen zwei aufeinanderfolgenden Ablesungen berechnet
|
||||
werden.
|
||||
|
||||
Verwende beim Erstellen Ihrer Antworten das folgende Datenbankschema:
|
||||
|
||||
MEIN_DATENBANKSCHEMA
|
||||
CREATE TABLE Addresses (
|
||||
ID INT PRIMARY KEY IDENTITY(1,1),
|
||||
StreetName NVARCHAR(100),
|
||||
HouseNumber NVARCHAR(10),
|
||||
City NVARCHAR(50),
|
||||
PostalCode NVARCHAR(10),
|
||||
Longitude FLOAT,
|
||||
Latitude FLOAT
|
||||
);
|
||||
|
||||
CREATE TABLE Meters (
|
||||
ID INT PRIMARY KEY IDENTITY(1,1),
|
||||
Signature NVARCHAR(11),
|
||||
MeterType NVARCHAR(3),
|
||||
AddressID INT,
|
||||
FOREIGN KEY (AddressID) REFERENCES Addresses(ID)
|
||||
);
|
||||
|
||||
CREATE TABLE Customers (
|
||||
ID INT PRIMARY KEY IDENTITY(1,1),
|
||||
FirstName NVARCHAR(100),
|
||||
LastName NVARCHAR(100),
|
||||
GasMeterID INT,
|
||||
EltMeterID INT,
|
||||
FOREIGN KEY (GasMeterID) REFERENCES Meters(ID),
|
||||
FOREIGN KEY (EltMeterID) REFERENCES Meters(ID)
|
||||
);
|
||||
|
||||
CREATE TABLE Readings (
|
||||
ID INT PRIMARY KEY IDENTITY(1,1),
|
||||
CustomerID INT,
|
||||
MeterID INT,
|
||||
ReadingDate DATE,
|
||||
ReadingValue INT,
|
||||
FOREIGN KEY (CustomerID) REFERENCES Customers(ID),
|
||||
FOREIGN KEY (MeterID) REFERENCES Meters(ID)
|
||||
);
|
||||
|
||||
Füge Spaltenüberschriften in die Abfrageergebnisse ein.
|
||||
|
||||
Gib deine Antwort immer im folgenden JSON-Format an:
|
||||
|
||||
JSON FORMAT
|
||||
{ "summary": "your-summary", "query": "your-query" }
|
||||
|
||||
Gib NUR JSON aus.
|
||||
Ersetze in der vorangehenden JSON-Antwort "your-query" durch die Microsoft SQL Server Query,
|
||||
@@ -45,15 +98,20 @@ def send_message(message: str) -> str:
|
||||
Gib immer alle Spalten der Tabelle an.
|
||||
Wenn die resultierende Abfrage nicht ausführbar ist, ersetze "your-query“ durch NA, aber ersetze
|
||||
trotzdem "your-query" durch eine Zusammenfassung der Abfrage.
|
||||
Verwende KEINE MySQL-Syntax.
|
||||
Verwende KEINE MySQL-Syntax, sondern AUSSCHLIESSLICH Microsoft SQL.
|
||||
Begrenze die SQL-Abfrage immer auf 100 Zeilen.
|
||||
Formatiere den Output bestmöglich.
|
||||
"""
|
||||
system_message = "Du bist ein hilfreicher Assistent."
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model=deployment_name,
|
||||
model=MODEL,
|
||||
messages=[
|
||||
{"role": "system", "content": system_message},
|
||||
{"role": "user", "content": message},
|
||||
],
|
||||
)
|
||||
return response.choices[0].message.content
|
||||
|
||||
result_str = response.choices[0].message.content.replace("```json\n", "").replace("```", "")
|
||||
if ("\n") not in result_str:
|
||||
result_str = result_str.replace("\\", "\n")
|
||||
return result_str
|
||||
|
||||
Reference in New Issue
Block a user