Add all project files
This commit is contained in:
commit
22a97d588e
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Exclude .venv directory
|
||||||
|
.venv/
|
||||||
|
# Exclude files in pages folder
|
||||||
|
pages/*
|
||||||
|
.DS_Store
|
118
app.py
Normal file
118
app.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
from pydantic import BaseModel, Field
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import streamlit as st
|
||||||
|
|
||||||
|
import ollama
|
||||||
|
from ollama import ChatResponse
|
||||||
|
|
||||||
|
MODEL = '<model>' # Type "ollama list" in terminal to see available models
|
||||||
|
|
||||||
|
class PythonScript(BaseModel):
|
||||||
|
script: str = Field(description="The Python script to be executed.")
|
||||||
|
comments: str = Field(description="Any additional notes or comments about the script.")
|
||||||
|
external_libraries: list[str] = Field(description="List of external libraries used in the script.")
|
||||||
|
|
||||||
|
|
||||||
|
class LLM:
|
||||||
|
def __init__(self, system_message: str, model: str = MODEL):
|
||||||
|
self.system_message = system_message
|
||||||
|
self.messages = [
|
||||||
|
{"role": "system", "content": system_message}
|
||||||
|
]
|
||||||
|
self.model = model
|
||||||
|
|
||||||
|
def generate(self, message: str, format: str) -> ChatResponse:
|
||||||
|
"""
|
||||||
|
Generate a chat response using the Ollama model.
|
||||||
|
|
||||||
|
This method appends the user message to the conversation history, sends it to the
|
||||||
|
Ollama chat model, and appends the assistant's response back to the history.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
message (str): The user's input message to send to the chat model.
|
||||||
|
format (str): The desired format for the response output.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ChatResponse: The complete response object from the Ollama chat model,
|
||||||
|
containing the assistant's reply and metadata.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
The method uses a low temperature (0.1) for more deterministic responses
|
||||||
|
and automatically maintains conversation history in self.messages.
|
||||||
|
"""
|
||||||
|
self.messages.append({"role": "user", "content": message})
|
||||||
|
|
||||||
|
response: ChatResponse = ollama.chat(
|
||||||
|
model=self.model,
|
||||||
|
messages=self.messages,
|
||||||
|
format=format,
|
||||||
|
options={'temperature': 0.1}
|
||||||
|
)
|
||||||
|
self.messages.append({"role": "assistant", "content": response.message.content})
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
# Initialize chat history in session state
|
||||||
|
if 'chat_history' not in st.session_state:
|
||||||
|
st.session_state.chat_history = []
|
||||||
|
if 'current_code' not in st.session_state:
|
||||||
|
st.session_state.current_code = None
|
||||||
|
if 'current_comments' not in st.session_state:
|
||||||
|
st.session_state.current_comments = None
|
||||||
|
if 'current_libraries' not in st.session_state:
|
||||||
|
st.session_state.current_libraries = []
|
||||||
|
|
||||||
|
st.title("Python Script Generator Chat")
|
||||||
|
|
||||||
|
# Display chat history
|
||||||
|
for i, (role, message) in enumerate(st.session_state.chat_history):
|
||||||
|
if role == 'user':
|
||||||
|
st.chat_message("user").write(message)
|
||||||
|
else:
|
||||||
|
st.chat_message("assistant").write(message)
|
||||||
|
|
||||||
|
user_input = st.chat_input("Describe what you want help doing or give feedback on the script")
|
||||||
|
|
||||||
|
if user_input:
|
||||||
|
st.session_state.chat_history.append(('user', user_input))
|
||||||
|
st.chat_message("user").write(user_input)
|
||||||
|
# Build system message and conversation context
|
||||||
|
system_message = """
|
||||||
|
You are a Python coder. Your task is to construct a Python script based on the user's input and feedback.
|
||||||
|
The script should be in a form of a Streamlit app, so make use of the Streamlit library for user interface elements.
|
||||||
|
Example: If a user want to upload a file, user st.file_uploader. If the user wants to input text, use st.text_input. Etc.
|
||||||
|
**IMPORTANT! The user can not change anything in the script, only interact with it via Streamlit UI elements.**
|
||||||
|
Therefore, don't user placeholders like "your_file" or "your_text". Instead, use Streamlit UI elements to get the input from the user.
|
||||||
|
If the user gives feedback, improve the previous script accordingly.
|
||||||
|
"""
|
||||||
|
# Build conversation context
|
||||||
|
conversation = "\n".join([
|
||||||
|
f"User: {msg}" if role == 'user' else f"Assistant: {msg}"
|
||||||
|
for role, msg in st.session_state.chat_history
|
||||||
|
])
|
||||||
|
llm = LLM(system_message=system_message)
|
||||||
|
response = llm.generate(conversation, format=PythonScript.model_json_schema())
|
||||||
|
answer = PythonScript.model_validate_json(response.message.content)
|
||||||
|
code = answer.script
|
||||||
|
comments = answer.comments
|
||||||
|
libraries = answer.external_libraries
|
||||||
|
st.session_state.current_code = code
|
||||||
|
st.session_state.current_comments = comments
|
||||||
|
st.session_state.current_libraries = libraries
|
||||||
|
st.session_state.chat_history.append(('assistant', comments + "\n\n" + code))
|
||||||
|
st.chat_message("assistant").write(comments)
|
||||||
|
st.code(code, language='python')
|
||||||
|
for library in libraries:
|
||||||
|
try:
|
||||||
|
__import__(library)
|
||||||
|
except ImportError:
|
||||||
|
st.write(f"Installing {library}...")
|
||||||
|
subprocess.check_call(["pip", "install", library])
|
||||||
|
with open("pages/user_app.py", "w") as f:
|
||||||
|
f.write(code)
|
||||||
|
|
||||||
|
elif st.session_state.current_code:
|
||||||
|
st.chat_message("assistant").write(st.session_state.current_comments)
|
||||||
|
with st.expander("View the code"):
|
||||||
|
st.code(st.session_state.current_code, language='python')
|
47
requirements.txt
Normal file
47
requirements.txt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
altair==5.5.0
|
||||||
|
annotated-types==0.7.0
|
||||||
|
anyio==4.9.0
|
||||||
|
attrs==25.3.0
|
||||||
|
blinker==1.9.0
|
||||||
|
cachetools==5.5.2
|
||||||
|
certifi==2025.4.26
|
||||||
|
charset-normalizer==3.4.2
|
||||||
|
click==8.2.1
|
||||||
|
exceptiongroup==1.3.0
|
||||||
|
gitdb==4.0.12
|
||||||
|
GitPython==3.1.44
|
||||||
|
h11==0.16.0
|
||||||
|
httpcore==1.0.9
|
||||||
|
httpx==0.28.1
|
||||||
|
idna==3.10
|
||||||
|
Jinja2==3.1.6
|
||||||
|
jsonschema==4.24.0
|
||||||
|
jsonschema-specifications==2025.4.1
|
||||||
|
MarkupSafe==3.0.2
|
||||||
|
narwhals==1.41.1
|
||||||
|
numpy==2.2.6
|
||||||
|
ollama==0.5.1
|
||||||
|
packaging==24.2
|
||||||
|
pandas==2.3.0
|
||||||
|
pillow==11.2.1
|
||||||
|
protobuf==6.31.1
|
||||||
|
pyarrow==20.0.0
|
||||||
|
pydantic==2.11.5
|
||||||
|
pydantic_core==2.33.2
|
||||||
|
pydeck==0.9.1
|
||||||
|
python-dateutil==2.9.0.post0
|
||||||
|
pytz==2025.2
|
||||||
|
referencing==0.36.2
|
||||||
|
requests==2.32.3
|
||||||
|
rpds-py==0.25.1
|
||||||
|
six==1.17.0
|
||||||
|
smmap==5.0.2
|
||||||
|
sniffio==1.3.1
|
||||||
|
streamlit==1.45.1
|
||||||
|
tenacity==9.1.2
|
||||||
|
toml==0.10.2
|
||||||
|
tornado==6.5.1
|
||||||
|
typing-inspection==0.4.1
|
||||||
|
typing_extensions==4.14.0
|
||||||
|
tzdata==2025.2
|
||||||
|
urllib3==2.4.0
|
Loading…
x
Reference in New Issue
Block a user