200 lines
7.3 KiB
Python
200 lines
7.3 KiB
Python
import openai
|
||
import subprocess
|
||
import time
|
||
import configparser
|
||
import json
|
||
import sys
|
||
|
||
# === 1. Načtení konfigurace z config.ini ===
|
||
config = configparser.ConfigParser()
|
||
config.read("config.ini")
|
||
|
||
openai.api_key = config["OpenAI"]["api_key"]
|
||
ASSISTANT_ID = config["OpenAI"]["assistant_id"]
|
||
thread_id = None
|
||
|
||
# === 2. Definice funkcí, které asistent může volat ===
|
||
FUNCTIONS = [
|
||
{
|
||
"name": "execute_shell_command",
|
||
"description": "Spustí shellový příkaz a vrátí jeho výstup.",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"command": {
|
||
"type": "string",
|
||
"description": "Shellový příkaz k vykonání."
|
||
}
|
||
},
|
||
"additionalProperties": False,
|
||
"required": ["command"]
|
||
}
|
||
}
|
||
]
|
||
|
||
# === 3. Pomocné funkce ===
|
||
def vytvor_nove_vlakno():
|
||
"""Vytvoří nové vlákno pro zachování historie konverzace."""
|
||
thread = openai.beta.threads.create()
|
||
return thread.id
|
||
|
||
def spust_prikaz(prikaz):
|
||
"""Spustí shellový příkaz a vrátí jeho výstup."""
|
||
try:
|
||
output = subprocess.check_output(prikaz, shell=True, stderr=subprocess.STDOUT, universal_newlines=True)
|
||
return output.strip()
|
||
except subprocess.CalledProcessError as e:
|
||
return f"Chyba při vykonávání příkazu:\n{e.output}"
|
||
|
||
def posli_dotaz_do_assistenta(prompt):
|
||
"""Odesílá dotaz v přirozeném jazyce do asistenta a vrací jeho odpověď."""
|
||
global thread_id
|
||
if thread_id is None:
|
||
thread_id = vytvor_nove_vlakno()
|
||
|
||
openai.beta.threads.messages.create(
|
||
thread_id=thread_id,
|
||
role="user",
|
||
content=prompt
|
||
)
|
||
|
||
run = openai.beta.threads.runs.create(
|
||
thread_id=thread_id,
|
||
assistant_id=ASSISTANT_ID
|
||
)
|
||
|
||
while True:
|
||
run_status = openai.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
|
||
if run_status.status == "completed":
|
||
break
|
||
time.sleep(1)
|
||
|
||
messages = openai.beta.threads.messages.list(thread_id=thread_id)
|
||
return messages.data[0].content[0].text.value
|
||
|
||
def posli_prikaz_do_assistenta(command):
|
||
"""Odesílá schválený příkaz k vykonání asistentovi a vrací výstup příkazu."""
|
||
global thread_id
|
||
if thread_id is None:
|
||
thread_id = vytvor_nove_vlakno()
|
||
|
||
run = openai.beta.threads.runs.create(
|
||
thread_id=thread_id,
|
||
assistant_id=ASSISTANT_ID,
|
||
instructions=f"Prosím, spusť tento příkaz: {command}"
|
||
)
|
||
|
||
while True:
|
||
run_status = openai.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
|
||
if run_status.status == "requires_action":
|
||
tool_calls = run_status.required_action.submit_tool_outputs.tool_calls
|
||
tool_outputs = []
|
||
for tool_call in tool_calls:
|
||
tool_name = tool_call.function.name
|
||
arguments = json.loads(tool_call.function.arguments)
|
||
if tool_name == "execute_shell_command":
|
||
vysledek = spust_prikaz(arguments["command"])
|
||
else:
|
||
vysledek = "Neznámá funkce."
|
||
tool_outputs.append({
|
||
"tool_call_id": tool_call.id,
|
||
"output": vysledek
|
||
})
|
||
openai.beta.threads.runs.submit_tool_outputs(
|
||
thread_id=thread_id,
|
||
run_id=run.id,
|
||
tool_outputs=tool_outputs
|
||
)
|
||
elif run_status.status == "completed":
|
||
break
|
||
time.sleep(1)
|
||
|
||
messages = openai.beta.threads.messages.list(thread_id=thread_id)
|
||
return messages.data[0].content[0].text.value
|
||
|
||
def is_command_response(response):
|
||
"""Vrací True, pokud odpověď začíná prefixem indikujícím návrh příkazu."""
|
||
return response.strip().lower().startswith("navrhovaný příkaz:")
|
||
|
||
def extract_command(response):
|
||
"""Odstraní prefix 'Navrhovaný příkaz:' a vrátí čistý shellový příkaz."""
|
||
prefix = "navrhovaný příkaz:"
|
||
if response.strip().lower().startswith(prefix):
|
||
return response.strip()[len(prefix):].strip()
|
||
return response.strip()
|
||
|
||
def provide_help():
|
||
"""Vrací text s nápovědou o funkcích Robovojtíka."""
|
||
help_text = (
|
||
"Nápověda k Robovojtikovi – Linuxový Shell Asistent:\n\n"
|
||
"Funkce:\n"
|
||
" • Převádí dotazy v přirozeném jazyce na návrhy shellových příkazů.\n"
|
||
" • Před spuštěním příkazu vždy čeká na potvrzení od uživatele.\n"
|
||
" • Přímé příkazy zadejte s prefixem 'cmd:' (např. 'cmd: ls -la').\n"
|
||
" • Pro ukončení Robovojtíka zadejte 'vypni' nebo 'exit'.\n\n"
|
||
"Pokud potřebujete další pomoc, zeptejte se!"
|
||
)
|
||
return help_text
|
||
|
||
# === 4. Hlavní interaktivní smyčka ===
|
||
def main():
|
||
print("Linuxový shell s OpenAI Assistant v2 API a funkcemi.")
|
||
print("Pro přímý příkaz použij prefix 'cmd:'")
|
||
print("Pro ukončení Robovojtíka zadej 'vypni' nebo 'exit'.")
|
||
print("Pro nápovědu zadej 'nápověda' nebo 'help'.")
|
||
|
||
while True:
|
||
user_input = input("\nZadej příkaz v přirozeném jazyce: ").strip()
|
||
|
||
# Ukončení Robovojtíka
|
||
if user_input.lower() in ["vypni", "exit"]:
|
||
potvrzeni = input("Skutečně chceš ukončit Robovojtíka? (y/n): ").strip().lower()
|
||
if potvrzeni == "y":
|
||
print("Ukončuji Robovojtíka...")
|
||
sys.exit(0)
|
||
else:
|
||
print("Ukončení zrušeno. Pokračuji.")
|
||
continue
|
||
|
||
# Zobrazení nápovědy
|
||
if user_input.lower() in ["nápověda", "help"]:
|
||
print("\n" + provide_help())
|
||
continue
|
||
|
||
# Přímý příkaz bez asistenta
|
||
if user_input.startswith("cmd:"):
|
||
command = user_input[4:].strip()
|
||
print(f"Rozpoznán přímý příkaz: {command}")
|
||
potvrzeni = input("Spustit tento příkaz? (y/n): ").strip().lower()
|
||
if potvrzeni == "y":
|
||
vysledek = spust_prikaz(command)
|
||
print("\nVýstup příkazu:")
|
||
print(vysledek)
|
||
else:
|
||
print("Příkaz nebyl spuštěn.")
|
||
continue
|
||
|
||
# Dotaz pro asistenta – očekává návrh příkazu
|
||
assistant_response = posli_dotaz_do_assistenta(user_input)
|
||
|
||
# Pokud odpověď nevypadá jako návrh příkazu, zobrazíme ji jako informativní odpověď
|
||
if not is_command_response(assistant_response):
|
||
print("\nRobovojtík odpovídá:")
|
||
print(assistant_response)
|
||
continue
|
||
|
||
# Pokud odpověď obsahuje navržený příkaz, vyzveme uživatele k potvrzení
|
||
print("\nRobovojtík navrhuje příkaz:")
|
||
print(assistant_response)
|
||
|
||
potvrzeni = input("Spustit tento příkaz? (y/n): ").strip().lower()
|
||
if potvrzeni == "y":
|
||
command_to_execute = extract_command(assistant_response)
|
||
execution_result = posli_prikaz_do_assistenta(command_to_execute)
|
||
print("\nVýstup příkazu:")
|
||
print(execution_result)
|
||
else:
|
||
print("Příkaz nebyl spuštěn. Čekám na další vstup.")
|
||
|
||
if __name__ == "__main__":
|
||
main( |