File size: 4,602 Bytes
b78c251
 
4760220
b78c251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e09959a
b78c251
 
e09959a
 
b78c251
 
 
 
e09959a
b78c251
 
 
 
e09959a
b78c251
 
 
e09959a
7500032
e09959a
7500032
 
e09959a
 
7500032
b78c251
 
e09959a
b78c251
e09959a
b78c251
 
 
 
 
 
 
 
 
 
e09959a
 
 
 
 
 
 
 
b78c251
 
 
e09959a
 
 
 
 
 
 
 
 
 
7500032
 
e09959a
 
 
b78c251
 
 
 
 
 
 
e09959a
 
 
 
 
b78c251
e09959a
 
b78c251
 
e09959a
 
 
b78c251
e09959a
b78c251
 
 
e09959a
 
 
 
b78c251
 
 
 
 
 
e09959a
b78c251
e09959a
 
 
 
 
 
 
 
b78c251
e09959a
 
b78c251
 
 
 
e09959a
b78c251
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import streamlit as st
from openai import OpenAI
from config import config
import requests
from prompts import SYSTEM_PROMPT


def setup_page():
    """Set up the Streamlit app's page configuration."""
    st.set_page_config(
        page_title="Ollama Chatbot",
        page_icon="🤖",
        layout="wide",
        initial_sidebar_state="auto",
    )


def initialize_session_state():
    """Initialize session state variables."""
    if "messages" not in st.session_state:
        st.session_state.messages = []
    if "ollama_server" not in st.session_state:
        st.session_state.ollama_server = config.OLLAMA_SERVER


def get_ollama_client():
    """Initialize the OpenAI client for Ollama."""
    base_url = f"{st.session_state.ollama_server}/v1/"
    return OpenAI(base_url=base_url, api_key="ollama")


def create_message(role, content):
    """Create a chat message dictionary."""
    return {"role": role, "content": content}


def fetch_chat_response(client, messages, model):
    """Fetch a response from the OpenAI client."""
    try:
        response = client.chat.completions.create(messages=messages, model=model)
        return response.choices[0].message.content
    except Exception as e:
        st.error(f"Error generating response: {e}")
        return None


def fetch_available_models(server_url):
    """Fetch available models from the Ollama server."""
    url = f"{server_url}/api/tags"
    try:
        response = requests.get(url)
        response.raise_for_status()
        return [item["model"] for item in response.json().get("models", [])]
    except requests.RequestException as e:
        st.error(f"Error fetching models: {e}")
        return []


def render_chat_messages():
    """Display chat messages in the UI."""
    for message in st.session_state.messages:
        role = message["role"]
        content = message["content"]
        if role == "user":
            st.chat_message("user").write(content)
        elif role == "assistant":
            st.chat_message("assistant").write(content)


def handle_user_input(client, model):
    """Handle user input and process responses."""
    if user_input := st.chat_input("Say something"):
        # Add system prompt if it's the first message
        if not st.session_state.messages:
            st.session_state.messages.append(create_message("system", SYSTEM_PROMPT))
        
        # Add user input to chat
        st.session_state.messages.append(create_message("user", user_input))
        st.chat_message("user").write(user_input)

        # Get assistant response
        response = fetch_chat_response(client, st.session_state.messages, model)
        if response:
            st.session_state.messages.append(create_message("assistant", response))
            st.chat_message("assistant").write(response)


def clear_chat():
    """Clear all chat messages."""
    st.session_state.messages = []


def sanitize_url(url):
    """Remove trailing slash from a URL if present."""
    return url.rstrip("/") if url.endswith("/") else url


def main():
    """Main function to run the chatbot application."""
    # Setup page and session state
    setup_page()
    initialize_session_state()
    
    # Initialize client
    client = get_ollama_client()

    # App Title
    st.title("Ollama Chatbot")
    st.sidebar.title("Settings")

    # Sidebar: Server and Models
    ollama_server = st.sidebar.text_input("Ollama Server", value=st.session_state.ollama_server)
    models = fetch_available_models(ollama_server)
    
    if not models:
        st.error("No models available. Please check the server connection.")
        return

    model = st.sidebar.selectbox("Select a Model", models)

    # Sidebar: System Prompt
    global SYSTEM_PROMPT
    updated_prompt = st.sidebar.text_area("System Prompt", value=SYSTEM_PROMPT)
    
    if st.sidebar.button("Update settings", use_container_width=True):
        st.session_state.ollama_server = sanitize_url(ollama_server)
        SYSTEM_PROMPT = updated_prompt
        
        # Update the system message if it exists, otherwise add it
        if st.session_state.messages and st.session_state.messages[0]["role"] == "system":
            st.session_state.messages[0]["content"] = SYSTEM_PROMPT
        elif not st.session_state.messages:
            st.session_state.messages.insert(0, create_message("system", SYSTEM_PROMPT))

    if st.sidebar.button("Clear Chat", use_container_width=True):
        clear_chat()

    # Main Chat Interface
    render_chat_messages()
    handle_user_input(client, model)


if __name__ == "__main__":
    main()