用语音命令管理数据库
我当时正在重温《哈利波特》系列,心里一直在想:老师和级长们到处给各个学院扣分!但是,他们会记录这么多班级的分数变化吗?数据完整性呢?可扩展性呢?写入冲突呢?他们肯定需要可扩展的东西,比如用于学院分数更新的发布-订阅系统。除了规模之外,语音识别必须有多好?
严肃地说,这让我开始思考——我们能用人工智能重现其中的一些吗?如果我们可以直接从语音转到 SQL 会怎么样?这就是我最终深入研究这个有趣的小实验的原因:使用 OpenAI 的 Whisper 进行转录,使用 Meta 的 Llama3 将文本转换为 SQL 查询,进行语音转 SQL。
这是我的方法,你也可以通过四个简单的步骤完成:
1、录制音频
我们通过使用简单的 Python 设置捕获音频来开始。使用 sounddevice
库,我们直接从麦克风录制音频,然后将其临时保存为 .wav
文件以便稍后转录。
import sounddevice as sd
import tempfile
import wave
# Function to record audio from the microphone and save it as a WAV file
def record_audio(duration, sample_rate=16000):
print("Recording...")
audio_data = sd.rec(int(duration * sample_rate), samplerate=sample_rate, channels=1, dtype='float32')
sd.wait() # Wait for the recording to finish
print("Recording finished.")
# Save the audio to a temporary WAV file
temp_wav = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
with wave.open(temp_wav.name, 'wb') as wf:
wf.setnchannels(1) # Mono channel
wf.setsampwidth(2) # 16-bit audio
wf.setframerate(sample_rate)
wf.writeframes(np.int16(audio_data * 32767)) # Convert float32 to int16
return temp_wav.name
一切从这里开始:一个简陋的语音命令准备转换成 SQL!
2、使用 Whisper 进行语音转文本
接下来,我们使用 OpenAI 的 Whisper 模型转录音频。此模型非常适合将语音转换为文本。这几乎就像拥有一个私人助理,可以听取你的命令并将其写下来 — 只是更加可靠和可扩展。
import whisper
import os
# Function to transcribe audio from the microphone using Whisper
def audio_to_text_from_mic(duration=5):
# Record audio from the microphone
audio_file = record_audio(duration)
# Load Whisper model
model = whisper.load_model("turbo") # You can use "turbo", "small", etc.
# Transcribe the recorded audio file
result = model.transcribe(audio_file)
# Delete the temporary audio file after transcription
os.remove(audio_file)
return result['text']
# Example usage
text = audio_to_text_from_mic(duration=3) # Record for 5 seconds
print("Transcription:", text)
Transcription: 10 points to Gryffindor
你的自然语言命令现在以文本形式呈现,可以进行下一级别的转换。
3、使用 Llama 3 将文本转换为 SQL
现在,真正的魔法来了 — 将转录的文本转换为 SQL 命令。使用 Llama 3 模型,我们输入自然语言命令(“为 Gryffindor 加 10 分”)并输出有效的 SQL 查询。
我们首先构建一个提示,提供有关数据库架构的上下文。在我们的例子中, house_points
表有两列: house_name
(房屋名称)和 points
(当前总分)。提示清楚地解释了这种结构,并指示模型返回格式良好的 SQL UPDATE 查询,而无需不必要的解释。
以下是分步操作:
a) 定义表架构:我们提供表的结构,让模型清楚地了解它是什么样子。架构指定表包含 house_name
和 points
。
table_schemas = """
house_points(house_name TEXT PRIMARY KEY, points INTEGER)
"""
b) 创建提示:我们生成一个提示,要求 Llama 3 将自然语言命令转换为 SQL UPDATE 查询。它明确要求仅使用查询以 JSON 格式响应,以确保输出干净且可用。
prompt = f"""
You are a SQL expert.
Please help to convert the following natural language command into a valid UPDATE SQL query. Your response should ONLY be based on the given context and follow the response guidelines and format instructions.
===Tables
{table_schemas}
===Response Guidelines
1. If the provided context is sufficient, please generate a valid query WITHOUT any explanations for the question.
2. Please format the query before responding.
3. Please always respond with a valid well-formed JSON object with the following format
4. There are only UPDATE queries and points are either added or deducted from a house
===Response Format
{{
"query": "A valid UPDATE SQL query when context is sufficient.",
}}
===command
{natural_language_text}
"""
c) 向 Llama 3 发送请求:然后使用 Ollama API 将文本发送到 LLM。模型处理请求并返回带有 SQL 查询的 JSON 对象。我们解析模型的 JSON 响应以提取 SQL 查询。如果出现问题(例如解析响应失败),则会返回错误。这确保了代码的稳健性。
import ollama
import json
response = ollama.chat(
model="llama3",
messages=[{"role": "user", "content": prompt}]
)
# Directly return the content as it should now be only the SQL query
# Parse the JSON response and return the SQL query if provided
response_content = response['message']['content']
# Directly return the content as it should now be only the SQL query
# Parse the JSON response and return the SQL query if provided
response_content = response['message']['content']
try:
response_json = json.loads(response_content)
if "query" in response_json:
return response_json["query"]
else:
return f"Error: {response_json.get('explanation', 'No explanation provided.')}"
except json.JSONDecodeError:
return "Error: Failed to parse response as JSON."
这样,你的“格兰芬多加 10 分”就变成了这样的 SQL 查询:
UPDATE house_points SET points = points + 10 WHERE house_name = 'Gryffindor';
3、运行 SQL 查询
最后,我们获取生成的 SQL 查询并在数据库上执行它以更新学院分数。但在深入执行查询之前,让我们确保初始设置已到位。
首先,你需要一个表来跟踪每个霍格沃茨学院的分数。以下是完成这项工作的简单表结构:
CREATE TABLE house_points (
house_name VARCHAR(50) PRIMARY KEY,
points INT
);
现在,将每栋房子的初始分数填入表格中。以下是一条快速 SQL 命令,可让每栋房子从 100 分开始:
INSERT INTO house_points (house_name, points)
VALUES ('Gryffindor', 100), ('Hufflepuff', 100), ('Ravenclaw', 100), ('Slytherin', 100);
数据库准备就绪后,您需要建立连接以运行查询。使用 SQLAlchemy 可使此操作变得非常简单。设置连接的方法如下:
from sqlalchemy import create_engine, text
engine = create_engine('postgresql://db_user:db_password@localhost/db_name')
def run_sql_query(query):
with engine.connect() as conn:
conn.execute(text(query))
conn.commit()
将 “db_user”、“db_password”和“db_name”替换为您的实际 PostgreSQL 凭据和数据库名称。
此函数获取由我们的语音转 SQL 脚本生成的 SQL 查询并在你的数据库上执行它。每次新的语音命令更新积分时,此函数都会运行相应的 SQL 并提交更改,确保实时更新学院积分表。
你刚刚通过语音命令更新了您的霍格沃茨学院积分——这太神奇了?
5、在 Streamlit 中将所有内容整合在一起
为了使你的项目更加用户友好,为什么不将整个解决方案包装到 Web 应用程序中?
使用 Streamlit,你可以构建一个交互式界面,用户可以在其中记录他们的语音命令,查看学院积分的实时更新,并查看学院徽标等视觉效果。
我已经在我的 Github 存储库中包含了完整的代码,你可以查看并自定义以满足你的需求。
6、结束语
只需几行代码,你就构建了一个语音驱动的 SQL 执行器。非常适合那些你内心的麦格教授,巧妙扣分的时刻。因此,无论你是管理霍格沃茨还是任何数据集,语音转 SQL 可能正是你节省时间所需的咒语。
原文链接:Speech-To-SQL Using OpenAI’s Whisper and Ollama (Llama3)
汇智网翻译整理,转载请标明出处