milestone done - added project descriptions, small changes

This commit is contained in:
Franziska Gerold 2026-05-29 22:54:04 +02:00
parent 4b39fb96bb
commit 311ffc9849
9 changed files with 155 additions and 34 deletions

View File

@ -19,8 +19,7 @@ def get_client() -> OpenAI:
client = get_client()
def send_message(message: str) -> str:
# hier gehts darum, die message vorzubereiten
# -> also nachricht aus den Chatfenster mit systemprompts und file_conntext verknüpfen
# Nachricht aus dem Chatfenster wird für qwen vorbereitet und mit Kontext über SystemPrompter ergänzt
prompt = generate_prompt(message)
response = send_prompt(prompt)
return response

View File

@ -2,7 +2,7 @@ import streamlit as st
import subprocess
def log_error(error_message):
#speichern wieder über session_state
#speichern des strukturierten outputs von qwen über session_state
st.session_state["bugs"] = error_message
@ -20,7 +20,6 @@ def format_debug_output(output: dict) -> str:
return "\n".join(lines)
#qwen
def format_output(text: bytes) -> str:
return text.decode('utf-8', errors='replace').strip()

View File

@ -6,6 +6,8 @@ from DebugLogger import log_error, format_output, format_error
def run_code(code: Path) -> None | str:
#führt Code aus angeklickter Datei im Editor aus. Sicherheitscheck über verbotene Imports und Funktionen geregelt
if "code_output" in st.session_state:
del st.session_state['code_output']
if "code_error" in st.session_state:
@ -29,20 +31,11 @@ def run_code(code: Path) -> None | str:
st.session_state['code_error'] = format_error(exc)
log_error(st.session_state['code_error'])
#brauchts diese Funktion noch? macht eigentlich schon run_code
def capture_output():
errors = st.session_state['code_error']
#if errors == 0:
# errors = "There are no errors"
return st.session_state['code_output'], errors
#aus der uebungsloesung
def check_code_safety(code: str) -> str | None:
#Analysiert den Code statisch nach verbotenen imports und builtins.
#analysiert den Code statisch nach verbotenen imports und builtins.
try:
tree = ast.parse(code)
except SyntaxError as e:

View File

@ -15,7 +15,7 @@ def read_file(file_path: Path) -> str:
return file.read()
def save_file(file_path: Path, content: str):
#wenn eine Datei im Code Editor abgeändert wird, soll die Funktion die Änderungen abspeichern
#wenn eine Datei im Code Editor abgeändert wird und der Save Button gedrückt wurde, speichert Funktion die Änderungen ab
with file_path.open('w') as file:
file.write(content)

View File

@ -1,7 +1,7 @@
from ddgs import DDGS
import re
def perform_search(query: str) -> dict:
#sucht Zusatzinfos im Internet
try:
results = DDGS().text(query, max_results=3)
return results
@ -12,7 +12,8 @@ def perform_search(query: str) -> dict:
def parse_results(results: list[dict]) -> list[dict]:
return [
#Limitiert Inhalt der Suchergebnisse auf 500 Zeichen, damit qwen nicht zu langen Prompt erhält
return [
{
"url": r.get("href", ""), #
"snippet": r.get("body", "")[:500]

View File

@ -3,7 +3,7 @@ from SearchManager import perform_search, parse_results
def generate_prompt(user_message: str) -> str:
# der key "debug" im session_state als toggle: wenn an, dann strukturierter output mit feedbackschleife über "bugs" key
if "debug" in st.session_state and st.session_state["debug"]:
system_content = """\
You are a code-review assistant. You ALWAYS respond with valid JSON and
@ -37,10 +37,11 @@ commentary. Your entire response must be parseable by json.loads().
context += (f" <bugs> {st.session_state['bugs']} </bugs>")
prompt = system_content + task + context
#st.session_state["last_prompt"] = (f"{prompt}")
st.session_state["last_prompt"] = (f"{prompt}")
return prompt
else:
# ohne "debug" key im session_state: unstrukturierter output
system_content = """\
<persona>
You are an experienced Python coding assistant.
@ -68,7 +69,7 @@ commentary. Your entire response must be parseable by json.loads().
prompt = system_content + task + context
#st.session_state["last_prompt"] = (f"{prompt}")
st.session_state["last_prompt"] = (f"{prompt}")
return prompt

19
app.py
View File

@ -3,28 +3,22 @@ import json
import streamlit as st
from pathlib import Path
from ChatManager import send_message
from FileManager import list_files, read_file, save_file, open_file
from FileManager import list_files, save_file, open_file
from ExecutionEngine import run_code
from DebugLogger import format_debug_output, log_error
#"Last sent prompt:",
#if "last_prompt" in st.session_state:
# st.session_state["last_prompt"]
#if "file_content" in st.session_state:
# st.session_state["file_content"]
#type(st.session_state["file_content"])
#print(type(st.session_state["file_content"]))
st.set_page_config(layout="wide")
# Initialisierung wichtiger keys im session_state
if not "file_content" in st.session_state:
st.session_state["file_content"] = ""
if not "selected_file" in st.session_state:
st.session_state["selected_file"] = ""
with st.sidebar:
# baut den Sidebar aus den vorhanden .py Dateien im Arbeitsverzeichnis
for file in list_files():
st.button(file.name, on_click=open_file, args=[file])
@ -35,7 +29,7 @@ with col_editor_output:
if "file_content" in st.session_state:
text = st.text_area("Code Editor", height="stretch", key="file_content")
# Preferred pattern for editor
# Oberfläche erhält zusätzliche Buttons, wenn eine Datei geöffnet wird
if st.session_state["selected_file"] != "":
st.button("Save", on_click=save_file, args=[st.session_state["selected_file"], st.session_state["file_content"]])
st.button("Execute Code", on_click=run_code, args=[st.session_state["selected_file"]])
@ -55,13 +49,13 @@ with col_chat:
if "messages" not in st.session_state:
st.session_state.messages = []
# Display History
# zeigt Chatverlauf als Abschnitt mit eigenem Scrollbalken
with st.container(border=True, height=500):
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.write(msg["content"])
# Input & Response
# regelt Verhalten bei Chat mit qwen. Nach Eingabe wird einer der Promptopitionen gewählt und fertiger Prompt sowie qwen Antwort in die messages gespeichert
message = st.chat_input("How can qwen help you?", key="chat")
internet = st.toggle("enable internet search", key="internet")
if "code_output" in st.session_state or "code_error" in st.session_state:
@ -72,7 +66,6 @@ with col_chat:
if "debug" in st.session_state and st.session_state["debug"]:
response = format_debug_output(json.loads(response))
log_error(response)
# st.session_state["bugs"] = response
st.session_state.messages.append({"role": "assistant", "content": response})
st.rerun()

135
project_description.md Normal file
View File

@ -0,0 +1,135 @@
**Lightweight Code Editor with AI integration**
##1. Introduction
This code editor was made as a project for the course Artificial Intelligence in Software Engineering I at FH Graubuenden.
Its purpose is to help with coding questions and debugging.
##2. Requirements
streamlit
openai
ddgs
dotenv
##3. Installation
- install requirements through pip
- aquire the environment variables thourgh FHGR
- connect to the FHGR VPN to get access to the AI model.
- run the app via terminal with "streamlit run app.py". A browser window will open.
##4. Architecture
The code is split up into frontend (app.py) and backend modules (FileManager, ChatManager, SystemPrompter, ExecutionEngine, DebugLogger and SearchManager).
A lot of functionality is realized through the use of the session_state from streamlit.
Since the streamlit app is rerun after each action the session_state is used to keep track of relevant information.
# 4.1 app.py
This module is the entrypoint for the streamlit functionality. It contains all elements that are visible when the program is run.
- sidebar:
The sidebar shows all python files within the working directory through fuctions found in the FileManager. Each file is represented by a clickable button.
There is no functionality to add or delete files from within the program. To change the available files the user has to manually add them to the directory.
Interacts with FileManger
- code editor:
The code editor shows the contents of the opened file. The contents can be changed, saved and also executed.
Interacts with FileManager, ExecutionEngine
- chat:
This element consists of an input area to send messages to the AI, two toggles to enable different modes as well as a scrollable history.
The first toggle is "enable internet search". This appends the results of an internet search to the prompt that is sent to the AI.
This means the results from the search are not primarily for the user, but for the AI to use recent information before responing to the user.
The second toggle "debug with qwen" appears only when a file was executed. This mode uses more structured output which is also sent to the next prompt for the AI.
With this feedback the AI can help with a more focused approach to find and fix bugs in the code. The user has to implement the fixes themself since the AI cannot change the contents of the file.
Interacts with ChatManager, Debuglogger
# 4.2 FileManager.py
This module manages the access to the working directory. It uses Path objects.
The open_file function is only used as a helper function to save the file path and contents to the session_state.
# 4.3 ChatManager.py
The environment variables are located in a .env file which is excluded from the gitea upload.
The qwen AI is accessed through the openai API client.
While this module sends the messages to the AI it is heavily dependend on the SystemPrompter to supply the relevant context for the finished prompt.
Interacts with SystemPrompter
# 4.4 SystemPrompter.py
This module handles all the context to add to the user message sent via the ChatManager. The instructions for the AI are structured with xml tags.
There are two modes which are chosen with a toggle. Both modes differ in the system component and sent context.
When the toggle is off the generated prompt includes system instructions which make the AI act as a coding assistant who gives short responses.
With the toggle on the output is structured with json and focussed on finding bugs in the provided code. The AI's response is also loaded into the session_state.
This means that subsequent messages to the AI keep its own responses therefore having the ability to iterate on them.
Interacts with SearchManager
# 4.5 ExecutionEngine.py
With this module the program can execute the opened file after clicking the corresponding button in the streamlit app.
There is a safety check before the subprocess is called to make sure no malicious actions can be made from within the program.
Interacts with Debuglogger
# 4.6 DebugLogger.py
This module handles making all outputs from various other module more readable and useable.
It saves the AI's response in the session_state to be able to send it with the next prompt when using the debug toggle.
# 4.7 SearchManager.py
This modules uses the duckduckgosearch API to make searching the internet possible.
The user does not directly see the search, but the result is sent with the prompt to the AI.
##5. Usage
The following examples illustrate how to use this program.
*I want to ask the AI about something in my file*
**user actions**: - click on button with name of the file
- write message to AI
- wait for response
- implement suggestions from AI
**interaction flow**: - st.sidebar uses list_files() to generate Buttons
- on_click uses open_file() to load content and file Path into session_state
- send_message() uses generate_prompt() to add system_prompt and context = file_content to the user_message
- response is displayed by st.session_state.messages
*I want to ask the AI about somehting in my file, but the AI has outdated info about the topic*
**user actions**: - click on button with name of the file
- activate "enable internet search" toggle
- write message to AI
- wait for response
- implement suggestions from AI
**interaction flow**: - st.sidebar uses list_files() to generate Buttons
- on_click uses open_file() to load content and file Path into session_state
- send_message() uses generate_prompt() to add system_prompt and context = file_content and results from perform_search() to the user_message
- response is displayed by st.session_state.messages
*I want to debug my code*
**user actions**: - click on button with name of the file
- click the "execute code" button
- write message to AI
- wait for response
- implement suggestions from AI
- write message to AI
- implement suggestions from AI
**interaction flow**: - st.sidebar uses list_files() to generate Buttons
- on_click uses open_file() to load content and file Path into session_state
- on_click uses run_code() to execute the file, results are formatted by format_output() or format_error()
- code_output or code_error are loaded into seassion_state
- send_message() uses generate_prompt() to add system_prompt which detects the "debug" toggle and adds context = file_content and code_output / code_error to the user_message
- response is displayed by st.session_state.messages
- send_message() uses generate_prompt() to add system_prompt which detects the "debug" toggle and adds context = file_content and code_output / code_error and debug response to the user_message
- response is displayed by st.session_state.messages

BIN
~$praesentation_ai_se.pptx Normal file

Binary file not shown.