Über den Bau Ihrer eigenen KI -Agenten? Sind Sie ständig von allen Schlagworts um Agenten überwältigt? Du bist nicht allein; Ich conflict auch dort. Es stehen zahlreiche Instruments zur Verfügung, und selbst herauszufinden, welche Sie wählen können, kann sich wie ein Projekt an sich anfühlen. Darüber hinaus gibt es Unsicherheit in Bezug auf Kosten und Infrastruktur. Werde ich zu viele Token konsumieren? Wie und wo kann ich meine Lösung bereitstellen?
Für eine Weile zögerte ich auch, etwas alleine zu bauen. Ich musste zuerst die Grundlagen verstehen, ein paar Beispiele sehen, um zu verstehen, wie die Dinge funktionieren, und dann einige praktische Erfahrungen ausprobieren, um diese Konzepte zum Leben zu erwecken. Nach vielen Nachforschungen landete ich endlich darauf Crewai – und es stellte sich heraus, dass es der perfekte Ausgangspunkt conflict. Es gibt zwei großartige Kurse von DeepLearning.ai: Multi -AI -Agentensysteme mit Crewai & Praktische Multi -AI -Agenten und fortgeschrittene Anwendungsfälle mit Crewai. Im Kurs hat der Ausbilder alles sehr deutlich erklärt, was Sie über KI -Agenten wissen müssen, um loszulegen. Es gibt mehr als 10 Fallstudien mit Codes im Kurs, die als guter Ausgangspunkt dienen.
Es reicht nicht mehr, nur etwas über Dinge zu lernen. Wenn Sie nicht das angewendet haben, was Sie gelernt haben, werden Sie wahrscheinlich die Grundlagen mit der Zeit vergessen. Wenn ich die Anwendungsfälle aus dem Kurs nur neu errege, gilt es nicht wirklich. Ich musste etwas bauen und es für mich umsetzen. Ich beschloss, einen Anwendungsfall aufzubauen, der eng mit dem zusammenhängt, mit dem ich arbeite. Als Datenanalyst und Ingenieur arbeite ich hauptsächlich mit Python und SQL. Ich dachte mir, wie cool es wäre, wenn ich einen Assistenten bauen könnte, der SQL -Abfragen basierend auf natürlicher Sprache erzeugen würde. Ich bin damit einverstanden, dass bereits viele Out-of-Field-Lösungen auf dem Markt verfügbar sind. Ich versuche nicht, das Rad hier neu zu erfinden. Mit diesem POC möchte ich lernen, wie solche Systeme aufgebaut werden und welche potenziellen Einschränkungen sind. Was ich hier aufdecken versuche, ist das, was nötig ist, um einen solchen Assistenten aufzubauen.

In diesem Beitrag werde ich Sie durch die Artwork und Weise führen, wie ich benutzt habe Crewai & Straffungzu bauen a Multi-Agent SQL Assistant . Dadurch können Benutzer a abfragen Sqlite Datenbank mit natürlicher Sprache. Um mehr Kontrolle über den gesamten Prozess zu haben, habe ich auch a integriert menschlicher Schleife Überprüfen Sie Plus, ich zeige die an LLM -Nutzungskosten Für jede Frage. Sobald eine Abfrage vom Assistenten generiert wurde, hat der Benutzer 3 Optionen: Akzeptieren und fahren Sie fort, wenn die Abfrage intestine aussieht, den Assistenten erneut versuchen, es erneut zu versuchen, wenn die Abfrage ausgeschaltet erscheint, oder den gesamten Prozess abbrechen, wenn sie nicht intestine funktioniert. Dieser Kontrollpunkt macht einen großen Unterschied – er gibt dem Benutzer mehr Strom, vermeidet es, schlechte Abfragen auszuführen, und hilft auch bei der Einsparung von LLM -Kosten auf lange Sicht.
Sie finden das gesamte Code -Repository Hier. Unten finden Sie die vollständige Projektstruktur:
SQL Assistant Crew Venture Construction
===================================
.
├── app.py (Streamlit UI)
├── predominant.py (terminal)
├── crew_setup.py
├── config
│ ├── brokers.yaml
│ └── duties.yaml
├── knowledge
│ └── sample_db.sqlite
├── utils
│ ├── db_simulator.py
│ └── helper.py

Die Agentarchitektur (mein Crewai -Crew)
Für mein SQL -Assistant -System brauchte ich mindestens 3 grundlegende Agenten, um den gesamten Prozess effizient zu bewältigen:
- Abfrageberatoragent Würde die natürlichen Sprachfragen des Benutzers mithilfe des Datenbankschemas als Kontext in eine SQL -Abfrage umwandeln.
- Abfrageturteiler Agent würde die vom Generator Agent erzeugte SQL -Abfrage nehmen und optimieren sie für Genauigkeit und Effizienz weiter.
- Compliance Checker Agent Würde die Abfrage nach potenzieller PII -Exposition überprüfen und ein Urteil darüber einreichen, ob die Abfrage konform ist oder nicht.
Jeder Agent muss 3 Kernattribute haben – eine Rolle (was der Agent sein soll), ein Ziel (was ist die Mission des Agenten) und eine Hintergrundgeschichte (setzen Sie die Persönlichkeit des Agenten, um zu leiten, wie es sich verhalten sollte). Ich habe aktiviert verbose=“True” Um den internen Denkprozess des Agenten anzuzeigen. Ich benutze das openai/gpt-4o-mini als das zugrunde liegende Sprachmodell für alle meine Agenten. Nach viel Versuch und Irrtum habe ich die festgelegt temperature=0.2 die Halluzinationen der Agenten zu reduzieren. Niedrigere Temperaturen machen das Modell deterministischer und liefern vorhersehbare Ausgänge (wie in meinem Fall SQL -Abfragen). Es gibt viele andere Parameter, die zur Verfügung stehen, wie max_tokens (Setzen Sie Grenzen für die Länge der Antwort), top_p (für die Kernprobenahme), allow_delegation (Um die Aufgabe an andere Agenten zu delegieren) usw. Wenn Sie einige andere LLMs verwenden, können Sie hier einfach den LLM -Modellnamen angeben. Sie können den gleichen LLM für alle oder verschiedene Agenten gemäß Ihren Anforderungen festlegen.
Unten finden Sie die YAML -Datei, die die Definitionen der Agenten enthält:
query_generator_agent:
position: Senior Information Analyst
aim: Translate pure language requests into correct and environment friendly SQL queries
backstory: >
You're an skilled analyst who is aware of SQL finest practices. You're employed with stakeholders to collect necessities
and switch their questions into clear, performant queries. You favor readable SQL with applicable filters and joins.
allow_delegation: False
verbose: True
mannequin: openai/gpt-4o-mini
temperature: 0.2
query_reviewer_agent:
position: SQL Code Reviewer
aim: Critically consider SQL for correctness, efficiency, and readability
backstory: >
You're a meticulous reviewer of SQL code. You determine inefficiencies, unhealthy practices, and logical errors, and
present strategies to enhance the question's efficiency and readability.
allow_delegation: False
verbose: True
mannequin: openai/gpt-4o-mini
temperature: 0.2
compliance_checker_agent:
position: Information Privateness and Governance Officer
aim: Guarantee SQL queries comply with knowledge compliance guidelines and keep away from PII publicity
backstory: >
You're liable for making certain queries don't leak or expose personally identifiable data (PII) or
violate firm insurance policies. You flag any unsafe or non-compliant practices.
allow_delegation: False
verbose: True
mannequin: openai/gpt-4o-mini
temperature: 0.2
Sobald Sie Ihre Agenten erstellt haben, besteht der nächste Schritt darin, die Aufgaben zu definieren, die sie ausführen sollten. Jede Aufgabe muss eine klare Beschreibung dessen haben, was der Agent tun soll. Es wird dringend empfohlen, dass Sie auch das festlegen expected_output Parameter, um die endgültige Reaktion des LLM zu formen. Es ist eine Möglichkeit, der LLM genau die Artwork von Antwort zu sagen, die Sie erwarten – es könnte sich um einen Textual content, eine Nummer, eine Abfrage oder sogar ein Artikel handeln. Die Beschreibung muss so detailliert und konkret wie möglich sein. Vagebeschreibungen führen nur zu vagen oder sogar völlig falschen Ausgängen. Ich musste die Beschreibungen während des Assessments mehrmals ändern, um die Qualität der Reaktion anzupassen, die der Agent generierte. Eine der Merkmale, die ich liebe, ist die Fähigkeit zu injizieren Dynamische Eingängein die Aufgabenbeschreibungen durch Bereitstellung von lockigen Klammern ({}). Diese Platzhalter können Benutzeranforderungen, Konzepte, Definitionen oder sogar Ausgaben früherer Agenten sein. All dies ermöglicht es den LLMs, genauere Ergebnisse zu erzielen.
query_task:
description: |
You're an skilled SQL assistant. Your job is to translate consumer requests into SQL queries utilizing ONLY the tables and columns listed under.
SCHEMA:
{db_schema}
USER REQUEST:
{user_input}
IMPORTANT:
- First, listing which tables and columns from the schema you'll use to reply the request.
- Then, write the SQL question.
- Solely use the tables and columns from the schema above.
- If the request can't be happy with the schema, return a SQL remark (beginning with --) explaining why.
- Do NOT invent tables or columns.
- Ensure the question matches the consumer's intent as intently as attainable.
expected_output: First, an inventory of tables and columns to make use of. Then, a syntactically right SQL question utilizing applicable filters, joins, and groupings.
review_task:
description: |
Overview the next SQL question for correctness, efficiency, and readability: {sql_query} and confirm that the question suits the schema: {db_schema}
Make sure that solely tables and columns from the offered schema are used.
IMPORTANT:
- First, solely overview the SQL question offered for correctness, efficiency, or readability
- Do NOT invent new tables or columns.
- If the Question is already right, return it unchanged.
- If the Question is just not right and can't be fastened, return a SQL remark (beginning with --) explaining why.
expected_output: An optimized or verified SQL question
compliance_task:
description: >
Overview the next SQL question for compliance violations, together with PII entry, unsafe utilization, or coverage violations.
Listing any points discovered, or state "No points discovered" if the question is compliant.
SQL Question: {reviewed_sqlquery}
expected_output: >
A markdown-formatted compliance report itemizing any flagged points, or stating that the question is compliant. Embody a transparent verdict on the prime (e.g., "Compliant" or "Points discovered")
Es ist eine gute Praxis, die Agenten- und Aufgabendefinitionen in separaten YAML -Dateien zu haben. Wenn Sie jemals die Definitionen von Agenten oder Aufgaben aktualisieren möchten, müssen Sie die YAML -Dateien nur ändern und die Codebasis überhaupt nicht berühren. Im crew_setup.py Datei, alles kommt zusammen. Ich habe die Agenten- und Aufgabenkonfigurationen aus ihren jeweiligen YAML -Dateien gelesen und geladen. Ich habe auch die Definitionen für alle erwarteten Ausgänge erstellt, die pydantische Modelle verwenden, um ihnen Struktur zu geben und zu validieren, was der LLM zurückkehren soll. Ich weise dann den Agenten ihre jeweiligen Aufgaben zu und montiere meine Crew. Es gibt mehrere Möglichkeiten, Ihre Crew je nach Anwendungsfall zu strukturieren. Eine einzelne Besatzung von Agenten kann Aufgaben nach Reihenfolge oder parallel ausführen. Alternativ können Sie mehrere Besatzungen erstellen, die jeweils für einen bestimmten Teil Ihres Workflows verantwortlich sind. Für meinen Anwendungsfall habe ich mich dafür entschieden, mehrere Besatzungen zu erstellen, um mehr Kontrolle über den Ausführungsfluss zu haben, indem ich einen Kontrollpunkt- und Kontrollkosten des Menschen in Schleife einfügte.
from crewai import Agent, Activity, Crew
from pydantic import BaseModel, Subject
from typing import Listing
import yaml
# Outline file paths for YAML configurations
information = {
'brokers': 'config/brokers.yaml',
'duties': 'config/duties.yaml',
}
# Load configurations from YAML information
configs = {}
for config_type, file_path in information.gadgets():
with open(file_path, 'r') as file:
configs(config_type) = yaml.safe_load(file)
# Assign loaded configurations to particular variables
agents_config = configs('brokers')
tasks_config = configs('duties')
class SQLQuery(BaseModel):
sqlquery: str = Subject(..., description="The uncooked sql question for the consumer enter")
class ReviewedSQLQuery(BaseModel):
reviewed_sqlquery: str = Subject(..., description="The reviewed sql question for the uncooked sql question")
class ComplianceReport(BaseModel):
report: str = Subject(..., description="A markdown-formatted compliance report with a verdict and any flagged points.")
# Creating Brokers
query_generator_agent = Agent(
config=agents_config('query_generator_agent')
)
query_reviewer_agent = Agent(
config=agents_config('query_reviewer_agent')
)
compliance_checker_agent = Agent(
config=agents_config('compliance_checker_agent')
)
# Creating Duties
query_task = Activity(
config=tasks_config('query_task'),
agent=query_generator_agent,
output_pydantic=SQLQuery
)
review_task = Activity(
config=tasks_config('review_task'),
agent=query_reviewer_agent,
output_pydantic=ReviewedSQLQuery
)
compliance_task = Activity(
config=tasks_config('compliance_task'),
agent=compliance_checker_agent,
context=(review_task),
output_pydantic=ComplianceReport
)
# Creating Crew objects for import
sql_generator_crew = Crew(
brokers=(query_generator_agent),
duties=(query_task),
verbose=True
)
sql_reviewer_crew = Crew(
brokers=(query_reviewer_agent),
duties=(review_task),
verbose=True
)
sql_compliance_crew = Crew(
brokers=(compliance_checker_agent),
duties=(compliance_task),
verbose=True
)
Ich habe eine lokale SQLite-Datenbank mit einigen Beispieldaten eingerichtet, um die realen Datenbankinteraktionen für meinen POC zu simulieren. Ich gap das Datenbankschema, das alle im System vorhandenen Tabellen und Spaltennamen umfasst. Ich habe dieses Schema später zusammen mit der ursprünglichen Benutzerabfrage als Kontext an die LLM gefüttert, um dem LLM zu helfen, eine SQL -Abfrage mit den ursprünglichen Tabellen und Spalten aus dem bereitgestellten Schema zu generieren und etwas nicht von selbst zu erfinden. Sobald der Generatoragent eine SQL -Abfrage erstellt hat, wird eine Überprüfung durch den Rezensentenvertreter gefolgt von einem Compliance -Verify vom Compliance -Agenten erhalten. Erst nach diesen Bewertungen erlaube ich, dass die überprüfte Abfrage in der Datenbank ausgeführt werden kann, damit die endgültigen Ergebnisse dem Benutzer über die Streamlit -Schnittstelle angezeigt werden. Durch Hinzufügen von Validierungs- und Sicherheitskontrollen stelle ich sicher, dass in der Datenbank nur qualitativ hochwertige Abfragen ausgeführt werden, in denen die unnötige Token-Nutzung minimiert und die Kosten langfristig berechnet werden.
import sqlite3
import pandas as pd
DB_PATH = "knowledge/sample_db.sqlite"
def setup_sample_db():
conn = sqlite3.join(DB_PATH)
cursor = conn.cursor()
# Drop tables in the event that they exist (for repeatability in dev)
cursor.execute("DROP TABLE IF EXISTS order_items;")
cursor.execute("DROP TABLE IF EXISTS orders;")
cursor.execute("DROP TABLE IF EXISTS merchandise;")
cursor.execute("DROP TABLE IF EXISTS clients;")
cursor.execute("DROP TABLE IF EXISTS staff;")
cursor.execute("DROP TABLE IF EXISTS departments;")
# Create richer instance tables
cursor.execute("""
CREATE TABLE merchandise (
product_id INTEGER PRIMARY KEY,
product_name TEXT,
class TEXT,
worth REAL
);
""")
cursor.execute("""
CREATE TABLE clients (
customer_id INTEGER PRIMARY KEY,
identify TEXT,
e-mail TEXT,
nation TEXT,
signup_date TEXT
);
""")
cursor.execute("""
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER,
order_date TEXT,
total_amount REAL,
FOREIGN KEY(customer_id) REFERENCES clients(customer_id)
);
""")
cursor.execute("""
CREATE TABLE order_items (
order_item_id INTEGER PRIMARY KEY,
order_id INTEGER,
product_id INTEGER,
amount INTEGER,
worth REAL,
FOREIGN KEY(order_id) REFERENCES orders(order_id),
FOREIGN KEY(product_id) REFERENCES merchandise(product_id)
);
""")
cursor.execute("""
CREATE TABLE staff (
employee_id INTEGER PRIMARY KEY,
identify TEXT,
department_id INTEGER,
hire_date TEXT
);
""")
cursor.execute("""
CREATE TABLE departments (
department_id INTEGER PRIMARY KEY,
department_name TEXT
);
""")
# Populate with mock knowledge
cursor.executemany("INSERT INTO merchandise VALUES (?, ?, ?, ?);", (
(1, 'Widget A', 'Widgets', 25.0),
(2, 'Widget B', 'Widgets', 30.0),
(3, 'Gadget X', 'Devices', 45.0),
(4, 'Gadget Y', 'Devices', 50.0),
(5, 'Thingamajig', 'Instruments', 15.0)
))
cursor.executemany("INSERT INTO clients VALUES (?, ?, ?, ?, ?);", (
(1, 'Alice', '(e-mail protected)', 'USA', '2023-10-01'),
(2, 'Bob', '(e-mail protected)', 'Canada', '2023-11-15'),
(3, 'Charlie', '(e-mail protected)', 'USA', '2024-01-10'),
(4, 'Diana', '(e-mail protected)', 'UK', '2024-02-20')
))
cursor.executemany("INSERT INTO orders VALUES (?, ?, ?, ?);", (
(1, 1, '2024-04-03', 100.0),
(2, 2, '2024-04-12', 150.0),
(3, 1, '2024-04-15', 120.0),
(4, 3, '2024-04-20', 180.0),
(5, 4, '2024-04-28', 170.0)
))
cursor.executemany("INSERT INTO order_items VALUES (?, ?, ?, ?, ?);", (
(1, 1, 1, 2, 25.0),
(2, 1, 2, 1, 30.0),
(3, 2, 3, 2, 45.0),
(4, 3, 4, 1, 50.0),
(5, 4, 5, 3, 15.0),
(6, 5, 1, 1, 25.0)
))
cursor.executemany("INSERT INTO staff VALUES (?, ?, ?, ?);", (
(1, 'Eve', 1, '2022-01-15'),
(2, 'Frank', 2, '2021-07-23'),
(3, 'Grace', 1, '2023-03-10')
))
cursor.executemany("INSERT INTO departments VALUES (?, ?);", (
(1, 'Gross sales'),
(2, 'Engineering'),
(3, 'HR')
))
conn.commit()
conn.shut()
def run_query(question):
strive:
conn = sqlite3.join(DB_PATH)
df = pd.read_sql_query(question, conn)
conn.shut()
return df.head().to_string(index=False)
besides Exception as e:
return f"Question failed: {e}"
def get_db_schema(db_path):
conn = sqlite3.join(db_path)
cursor = conn.cursor()
schema = ""
cursor.execute("SELECT identify FROM sqlite_master WHERE kind='desk';")
tables = cursor.fetchall()
for table_name, in tables:
cursor.execute(f"SELECT sql FROM sqlite_master WHERE kind='desk' AND identify='{table_name}';")
create_stmt = cursor.fetchone()(0)
schema += create_stmt + ";nn"
conn.shut()
return schema
def get_structured_schema(db_path):
conn = sqlite3.join(db_path)
cursor = conn.cursor()
cursor.execute("SELECT identify FROM sqlite_master WHERE kind='desk';")
tables = cursor.fetchall()
strains = ("Accessible tables and columns:")
for table_name, in tables:
cursor.execute(f"PRAGMA table_info({table_name})")
columns = (row(1) for row in cursor.fetchall())
strains.append(f"- {table_name}: {', '.be a part of(columns)}")
conn.shut()
return 'n'.be a part of(strains)
if __name__ == "__main__":
setup_sample_db()
print("Pattern database created.")
LLMs Gebühr nach Token – einfache Textfragmente. Für jedes LLM draußen gibt es ein Preismodell, das auf der Anzahl der Eingangs- und Ausgangs -Token basiert, die normalerweise professional Million Token in Rechnung gestellt werden. Eine vollständige Preisliste aller OpenAI -Modelle finden Sie in der offiziellen Preisseite Hier. Für gpt-4o-miniDie Enter -Token kosten 0,15 USD/m, während die Ausgangs -Token 0,60 USD/m kosten. Um die Gesamtkosten für eine LLM -Anfrage zu verarbeiten, habe ich die folgenden Helferfunktionen in erstellt helper.py Berechnung der Gesamtkosten auf der Grundlage der Token -Nutzung in einer Anfrage.
import re
def extract_token_counts(token_usage_str):
immediate = completion = 0
prompt_match = re.search(r'prompt_tokens=(d+)', token_usage_str)
completion_match = re.search(r'completion_tokens=(d+)', token_usage_str)
if prompt_match:
immediate = int(prompt_match.group(1))
if completion_match:
completion = int(completion_match.group(1))
return immediate, completion
def calculate_gpt4o_mini_cost(prompt_tokens, completion_tokens):
input_cost = (prompt_tokens / 1000) * 0.00015
output_cost = (completion_tokens / 1000) * 0.0006
return input_cost + output_cost
Der app.py Die Datei erstellt eine leistungsstarke Streamlit -Anwendung, mit der der Benutzer die SQLite -Datenbank mithilfe der natürlichen Sprache auffordert. Hinter den Kulissen ist meine Set von Crewai -Agenten in Bewegung. Nachdem der erste Agent eine SQL -Abfrage generiert hat, wird er in der App für den Benutzer angezeigt. Der Benutzer hat drei Optionen:
- Bestätigen und Überprüfung – Wenn der Benutzer die Abfrage akzeptabel findet und fortgesetzt werden möchte
- Versuchen Sie es erneut – wenn der Benutzer mit der Abfrage nicht zufrieden ist und möchte, dass der Agent erneut eine neue Abfrage generiert
- Abrufen – Wenn der Benutzer den Prozess hier stoppen möchte
Zusammen mit den oben genannten Optionen werden die für diese Anfrage entstandenen LLM -Kosten auf dem Bildschirm angezeigt. Sobald der Benutzer auf das klickt “Verify & Overview” Button, die SQL -Abfrage wird die nächsten beiden Überprüfungsebenen durchlaufen. Der Rezensent -Agent optimiert es für Korrektheit und Effizienz, gefolgt vom Konformitätsagenten, der die Einhaltung von Einhaltung überprüft. Wenn die Abfrage konform ist, wird sie in der SQLite -Datenbank ausgeführt. Die endgültigen Ergebnisse und die im gesamten Prozess entstandenen kumulativen LLM -Kosten werden auf der App -Schnittstelle angezeigt. Der Benutzer ist nicht nur während des Prozesses kontrolliert, sondern ist auch kostenbewusst.
import streamlit as st
from crew_setup import sql_generator_crew, sql_reviewer_crew, sql_compliance_crew
from utils.db_simulator import get_structured_schema, run_query
import sqlparse
from utils.helper import extract_token_counts, calculate_gpt4o_mini_cost
DB_PATH = "knowledge/sample_db.sqlite"
# Cache the schema, however permit clearing it
@st.cache_data(show_spinner=False)
def load_schema():
return get_structured_schema(DB_PATH)
st.title("SQL Assistant Crew")
st.markdown("""
Welcome to the SQL Assistant Crew!
This app helps you to work together together with your database utilizing pure language. Merely kind your knowledge query or request (for instance, "Present me the highest 5 merchandise by whole income for April 2024"), and our multi-agent system will:
1. **Generate** a related SQL question to your request,
2. **Overview** and optimize the question for correctness and efficiency,
3. **Verify** the question for compliance and knowledge security,
4. **Execute** the question (if compliant) and show the outcomes.
You may as well refresh the database schema in case your knowledge adjustments.
This device is ideal for enterprise customers, analysts, and anybody who desires to question knowledge with out writing SQL by hand!
""")
st.write("The schema of the database is saved. For those who consider the schema is wrong, you'll be able to refresh it by clicking the button under.")
# Add a refresh button
if st.button("Refresh Schema"):
load_schema.clear() # Clear the cache so subsequent name reloads from DB
st.success("Schema refreshed from database.")
# At all times get the (probably cached) schema
db_schema = load_schema()
with st.expander("Present database schema"):
st.code(db_schema)
st.write("Enter your request in pure language and let the crew generate, overview, and verify compliance for the SQL question.")
if "generated_sql" not in st.session_state:
st.session_state("generated_sql") = None
if "awaiting_confirmation" not in st.session_state:
st.session_state("awaiting_confirmation") = False
if "reviewed_sql" not in st.session_state:
st.session_state("reviewed_sql") = None
if "compliance_report" not in st.session_state:
st.session_state("compliance_report") = None
if "query_result" not in st.session_state:
st.session_state("query_result") = None
if "regenerate_sql" not in st.session_state:
st.session_state("regenerate_sql") = False
if "llm_cost" not in st.session_state:
st.session_state("llm_cost") = 0.0
user_prompt = st.text_input("Enter your request (e.g., 'Present me the highest 5 merchandise by whole income for April 2024'):")
# Mechanically regenerate SQL if 'Attempt Once more' was clicked
if st.session_state.get("regenerate_sql"):
if user_prompt.strip():
strive:
gen_output = sql_generator_crew.kickoff(inputs={"user_input": user_prompt, "db_schema": db_schema})
raw_sql = gen_output.pydantic.sqlquery
st.session_state("generated_sql") = raw_sql
st.session_state("awaiting_confirmation") = True
st.session_state("reviewed_sql") = None
st.session_state("compliance_report") = None
st.session_state("query_result") = None
# LLM price monitoring
token_usage_str = str(gen_output.token_usage)
prompt_tokens, completion_tokens = extract_token_counts(token_usage_str)
price = calculate_gpt4o_mini_cost(prompt_tokens, completion_tokens)
st.session_state("llm_cost") += price
st.data(f"Your LLM price to date: ${st.session_state('llm_cost'):.6f}")
besides Exception as e:
st.error(f"An error occurred: {e}")
else:
st.warning("Please enter a immediate.")
st.session_state("regenerate_sql") = False
# Step 1: Generate SQL
if st.button("Generate SQL"):
if user_prompt.strip():
strive:
gen_output = sql_generator_crew.kickoff(inputs={"user_input": user_prompt, "db_schema": db_schema})
# st.write(gen_output) # Optionally hold for debugging
raw_sql = gen_output.pydantic.sqlquery
st.session_state("generated_sql") = raw_sql
st.session_state("awaiting_confirmation") = True
st.session_state("reviewed_sql") = None
st.session_state("compliance_report") = None
st.session_state("query_result") = None
# LLM price monitoring
token_usage_str = str(gen_output.token_usage)
prompt_tokens, completion_tokens = extract_token_counts(token_usage_str)
price = calculate_gpt4o_mini_cost(prompt_tokens, completion_tokens)
st.session_state("llm_cost") += price
besides Exception as e:
st.error(f"An error occurred: {e}")
else:
st.warning("Please enter a immediate.")
# Solely present immediate and generated SQL when awaiting affirmation
if st.session_state.get("awaiting_confirmation") and st.session_state.get("generated_sql"):
st.subheader("Generated SQL")
formatted_generated_sql = sqlparse.format(st.session_state("generated_sql"), reindent=True, keyword_case='higher')
st.code(formatted_generated_sql, language="sql")
st.data(f"Your LLM price to date: ${st.session_state('llm_cost'):.6f}")
col1, col2, col3 = st.columns(3)
with col1:
if st.button("Verify and Overview"):
strive:
# Step 2: Overview SQL
review_output = sql_reviewer_crew.kickoff(inputs={"sql_query": st.session_state("generated_sql"),"db_schema": db_schema})
reviewed_sql = review_output.pydantic.reviewed_sqlquery
st.session_state("reviewed_sql") = reviewed_sql
# LLM price monitoring for reviewer
token_usage_str = str(review_output.token_usage)
prompt_tokens, completion_tokens = extract_token_counts(token_usage_str)
price = calculate_gpt4o_mini_cost(prompt_tokens, completion_tokens)
st.session_state("llm_cost") += price
# Step 3: Compliance Verify
compliance_output = sql_compliance_crew.kickoff(inputs={"reviewed_sqlquery": reviewed_sql})
compliance_report = compliance_output.pydantic.report
# LLM price monitoring for compliance
token_usage_str = str(compliance_output.token_usage)
prompt_tokens, completion_tokens = extract_token_counts(token_usage_str)
price = calculate_gpt4o_mini_cost(prompt_tokens, completion_tokens)
st.session_state("llm_cost") += price
# Take away duplicate header if current
strains = compliance_report.splitlines()
if strains and contours(0).strip().decrease().startswith("# compliance report"):
compliance_report = "n".be a part of(strains(1:)).lstrip()
st.session_state("compliance_report") = compliance_report
# Solely execute if compliant
if "compliant" in compliance_report.decrease():
end result = run_query(reviewed_sql)
st.session_state("query_result") = end result
else:
st.session_state("query_result") = None
st.session_state("awaiting_confirmation") = False
st.data(f"Your LLM price to date: ${st.session_state('llm_cost'):.6f}")
st.rerun()
besides Exception as e:
st.error(f"An error occurred: {e}")
with col2:
if st.button("Attempt Once more"):
st.session_state("generated_sql") = None
st.session_state("awaiting_confirmation") = False
st.session_state("reviewed_sql") = None
st.session_state("compliance_report") = None
st.session_state("query_result") = None
st.session_state("regenerate_sql") = True
st.rerun()
with col3:
if st.button("Abort"):
st.session_state.clear()
st.rerun()
# After overview, solely present reviewed SQL, compliance, and end result
elif st.session_state.get("reviewed_sql"):
st.subheader("Reviewed SQL")
formatted_sql = sqlparse.format(st.session_state("reviewed_sql"), reindent=True, keyword_case='higher')
st.code(formatted_sql, language="sql")
st.subheader("Compliance Report")
st.markdown(st.session_state("compliance_report"))
if st.session_state.get("query_result"):
st.subheader("Question Consequence")
st.code(st.session_state("query_result"))
# LLM price show on the backside
st.data(f"Your LLM price to date: ${st.session_state('llm_cost'):.6f}")
Hier ist eine kurze Demo der App in Aktion. Ich habe es gebeten, die High -Produkte basierend auf dem Gesamtumsatz anzuzeigen. Der Assistent hat eine SQL -Abfrage generiert, und ich klickte darauf “Verify and Overview”. Die Abfrage conflict bereits intestine optimiert, sodass der Rezensentenagent die gleiche Abfrage ohne Änderungen zurückgab. Als nächstes überprüfte der Compliance Verify Agent die Abfrage und bestätigte, dass es sicher conflict, dass es sicher ist – keine riskanten Vorgänge oder die Exposition sensibler Daten. Nachdem die beiden Bewertungen bestanden hatten, wurde die Abfrage gegen die Beispieldatenbank ausgeführt und die Ergebnisse wurden angezeigt. Für diesen gesamten Prozess betrug die LLM -Nutzungskosten nur 0,001349 USD.

Hier ist ein weiteres Beispiel, in dem ich die App bitte, zu ermitteln, welche Produkte die meisten Renditen erzielen. Das Schema gibt jedoch keine Informationen über die Rückgabe. Infolgedessen erzeugt der Assistent keine Abfrage und gibt den gleichen Grund aus. Bis zu dieser Section betrugen die LLM -Kosten 0,00853 USD. Da es keinen Sinn macht, eine nicht existierende Abfrage zu überprüfen oder auszuführen, habe ich einfach geklickt “Abort” um den Prozess anmutig zu beenden.

Crewai ist unglaublich leistungsfähig für den Aufbau von Multi-Agent-Systemen. Durch das Kombinieren mit stromanischer Sprache kann man problemlos eine einfache interaktive Benutzeroberfläche erstellen, um mit dem System zu arbeiten. In diesem POC habe ich untersucht, wie man ein Aspect des Menschen in Schleife hinzufügt, um die Kontrolle und Transparenz während des gesamten Workflows aufrechtzuerhalten. Ich habe auch verfolgt, wie viele Token bei jedem Schritt konsumiert wurden, um dem Benutzer dabei zu helfen, während des Prozesses kostenpflichtig zu bleiben. Mit Hilfe eines Compliance-Vertreters habe ich einige grundlegende Sicherheitsmaßnahmen erzwungen, indem ich riskante oder pii-expositionsbedingte Abfragen blockierte. Ich habe die Temperatur des Modells abgestimmt und die Aufgabenbeschreibungen iterativ verfeinert, um die Ausgangsqualität zu verbessern und Halluzinationen zu reduzieren. Ist es perfekt? Die Antwort ist nein. Es gibt immer noch einige Male, in denen das System halluziniert. Wenn ich dies im Maßstab umsetze, wären die LLM -Kosten ein größeres Downside. Im wirklichen Leben sind die Datenbanken komplex, und als solches wird ihr Schema auch riesig sein. Ich müsste die Arbeit mit RAG (Abruf Augmented Era) untersuchen, um nur relevante Schema -Snippets in die LLM zu füttern, den Speicher des Agenten zu optimieren und Caching zu verwenden, um redundante API -Aufrufe zu vermeiden.
Letzte Gedanken
Dies conflict ein lustiges Projekt, das die Kraft von LLMs, die Praktikabilität von Strom und die modulare Intelligenz von Crewai kombiniert. Wenn Sie daran interessiert sind, intelligente Agenten für die Dateninteraktion aufzubauen, probieren Sie es aus – oder geben Sie das Repo auf und bauen Sie darauf auf!
Bevor du gehst …
Folgen Sie mir, damit Sie keine neuen Beiträge verpassen, die ich in Zukunft schreibe. Sie werden mehr von meinen Artikeln finden Meine Profilseite. Sie können sich auch mit mir verbinden LinkedIn oder X!
