Spaces:
Sleeping
Sleeping
Commit ·
96a17a6
1
Parent(s): cc807a2
feat: implement DeepSeek Janus chat interface
Browse files- Add streaming response generation
- Implement chat UI with real-time updates
- Add multi-page structure
- Update dependencies
- Improve error handling
- .gitignore +3 -1
- app.py +15 -3
- pages/01_chat.py +83 -69
- utils.py +34 -24
.gitignore
CHANGED
|
@@ -1,5 +1,7 @@
|
|
| 1 |
__pycache__/
|
| 2 |
*.py[cod]
|
|
|
|
|
|
|
| 3 |
*.so
|
| 4 |
.Python
|
| 5 |
env/
|
|
@@ -7,5 +9,5 @@ build/
|
|
| 7 |
dist/
|
| 8 |
eggs/
|
| 9 |
*.egg-info/
|
| 10 |
-
.
|
| 11 |
generated_image.png
|
|
|
|
| 1 |
__pycache__/
|
| 2 |
*.py[cod]
|
| 3 |
+
.env*
|
| 4 |
+
.venv
|
| 5 |
*.so
|
| 6 |
.Python
|
| 7 |
env/
|
|
|
|
| 9 |
dist/
|
| 10 |
eggs/
|
| 11 |
*.egg-info/
|
| 12 |
+
.streamlit/secrets.toml
|
| 13 |
generated_image.png
|
app.py
CHANGED
|
@@ -24,11 +24,23 @@ st.markdown("""
|
|
| 24 |
""", unsafe_allow_html=True)
|
| 25 |
|
| 26 |
st.title("🧠 DeepSeek AI Assistant")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
st.markdown("""
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
-
|
| 31 |
-
-
|
|
|
|
|
|
|
| 32 |
""")
|
| 33 |
|
| 34 |
@st.cache_resource
|
|
|
|
| 24 |
""", unsafe_allow_html=True)
|
| 25 |
|
| 26 |
st.title("🧠 DeepSeek AI Assistant")
|
| 27 |
+
|
| 28 |
+
if "model_loaded" not in st.session_state:
|
| 29 |
+
st.session_state.model_loaded = False
|
| 30 |
+
|
| 31 |
st.markdown("""
|
| 32 |
+
👈 Select 'Chat' from the sidebar to start chatting!
|
| 33 |
+
|
| 34 |
+
### Features:
|
| 35 |
+
- Real-time response generation
|
| 36 |
+
- Context-aware conversations
|
| 37 |
+
- Professional responses
|
| 38 |
+
- Memory efficient
|
| 39 |
|
| 40 |
+
### Tips:
|
| 41 |
+
- Be specific in your questions
|
| 42 |
+
- Use clear language
|
| 43 |
+
- Start with simple queries
|
| 44 |
""")
|
| 45 |
|
| 46 |
@st.cache_resource
|
pages/01_chat.py
CHANGED
|
@@ -3,77 +3,91 @@ from utils import load_model, generate_stream
|
|
| 3 |
import time
|
| 4 |
|
| 5 |
def init_chat():
|
| 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 |
-
with
|
| 32 |
-
|
| 33 |
-
with st.chat_message(msg["role"]):
|
| 34 |
-
st.markdown(msg["content"])
|
| 35 |
|
| 36 |
-
#
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
st.
|
|
|
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
st.session_state.tokenizer
|
| 62 |
-
)
|
| 63 |
-
|
| 64 |
-
if response:
|
| 65 |
-
st.session_state.messages.append({
|
| 66 |
-
"role": "assistant",
|
| 67 |
-
"content": response
|
| 68 |
-
})
|
| 69 |
-
|
| 70 |
-
except Exception as e:
|
| 71 |
-
st.error("Failed to generate response. Please try again.")
|
| 72 |
-
st.error(f"Error details: {str(e)}")
|
| 73 |
-
|
| 74 |
-
finally:
|
| 75 |
-
st.session_state.generating = False
|
| 76 |
-
|
| 77 |
-
except Exception as e:
|
| 78 |
-
st.error(f"Application error: {str(e)}")
|
| 79 |
-
st.button("🔄 Restart App")
|
|
|
|
| 3 |
import time
|
| 4 |
|
| 5 |
def init_chat():
|
| 6 |
+
try:
|
| 7 |
+
# Initialize session state
|
| 8 |
+
if "messages" not in st.session_state:
|
| 9 |
+
st.session_state.messages = []
|
| 10 |
+
if "generating" not in st.session_state:
|
| 11 |
+
st.session_state.generating = False
|
| 12 |
+
|
| 13 |
+
# Load model if needed
|
| 14 |
+
if "model" not in st.session_state or "tokenizer" not in st.session_state:
|
| 15 |
+
with st.spinner("📚 Initializing AI model..."):
|
| 16 |
+
st.session_state.model, st.session_state.tokenizer = load_model()
|
| 17 |
+
|
| 18 |
+
except Exception as e:
|
| 19 |
+
st.error(f"Initialization error: {str(e)}")
|
| 20 |
+
st.button("🔄 Retry Loading")
|
| 21 |
+
st.stop()
|
| 22 |
|
| 23 |
+
st.title("💭 Chat Interface")
|
| 24 |
+
|
| 25 |
+
# Initialize
|
| 26 |
+
init_chat()
|
| 27 |
+
|
| 28 |
+
# Verify model loaded
|
| 29 |
+
if not st.session_state.get("model_loaded", False):
|
| 30 |
+
st.warning("⚠️ Model not fully loaded. Please wait...")
|
| 31 |
+
st.stop()
|
| 32 |
+
|
| 33 |
+
# Sidebar controls
|
| 34 |
+
with st.sidebar:
|
| 35 |
+
st.markdown("### Chat Controls")
|
| 36 |
+
cols = st.columns(2)
|
| 37 |
+
with cols[0]:
|
| 38 |
+
if st.button("🗑️ Clear Chat", use_container_width=True):
|
| 39 |
+
st.session_state.messages = []
|
| 40 |
+
st.session_state.generating = False
|
| 41 |
+
st.rerun()
|
| 42 |
+
with cols[1]:
|
| 43 |
+
if st.button("🔄 Reset Model", use_container_width=True):
|
| 44 |
+
st.session_state.clear()
|
| 45 |
+
st.cache_resource.clear()
|
| 46 |
+
st.rerun()
|
| 47 |
+
|
| 48 |
+
# Chat history
|
| 49 |
+
chat_container = st.container()
|
| 50 |
+
with chat_container:
|
| 51 |
+
for msg in st.session_state.messages:
|
| 52 |
+
with st.chat_message(msg["role"]):
|
| 53 |
+
st.markdown(msg["content"])
|
| 54 |
+
|
| 55 |
+
# Input handling
|
| 56 |
+
if prompt := st.chat_input(
|
| 57 |
+
"Ask me anything...",
|
| 58 |
+
disabled=st.session_state.generating
|
| 59 |
+
):
|
| 60 |
+
# Update generating state
|
| 61 |
+
st.session_state.generating = True
|
| 62 |
|
| 63 |
+
# Show user message
|
| 64 |
+
st.session_state.messages.append({"role": "user", "content": prompt})
|
| 65 |
+
with st.chat_message("user"):
|
| 66 |
+
st.markdown(prompt)
|
|
|
|
|
|
|
| 67 |
|
| 68 |
+
# Generate and show response
|
| 69 |
+
with st.chat_message("assistant"):
|
| 70 |
+
try:
|
| 71 |
+
context = "\n".join([
|
| 72 |
+
f"{m['role']}: {m['content']}"
|
| 73 |
+
for m in st.session_state.messages[-3:]
|
| 74 |
+
])
|
| 75 |
|
| 76 |
+
response = generate_stream(
|
| 77 |
+
context,
|
| 78 |
+
st.session_state.model,
|
| 79 |
+
st.session_state.tokenizer
|
| 80 |
+
)
|
| 81 |
|
| 82 |
+
if response:
|
| 83 |
+
st.session_state.messages.append({
|
| 84 |
+
"role": "assistant",
|
| 85 |
+
"content": response
|
| 86 |
+
})
|
| 87 |
+
|
| 88 |
+
except Exception as e:
|
| 89 |
+
st.error("Failed to generate response. Please try again.")
|
| 90 |
+
st.error(f"Error details: {str(e)}")
|
| 91 |
+
|
| 92 |
+
finally:
|
| 93 |
+
st.session_state.generating = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utils.py
CHANGED
|
@@ -9,30 +9,37 @@ logging.basicConfig(level=logging.INFO)
|
|
| 9 |
|
| 10 |
@st.cache_resource
|
| 11 |
def load_model():
|
|
|
|
|
|
|
|
|
|
| 12 |
model_name = "deepseek-ai/Janus-Pro-7B"
|
| 13 |
|
| 14 |
try:
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
| 34 |
except Exception as e:
|
| 35 |
-
st.error(f"Error loading model: {str(e)}")
|
|
|
|
| 36 |
st.stop()
|
| 37 |
|
| 38 |
def stream_tokens(response: str, delay: float = 0.01) -> Generator[str, None, None]:
|
|
@@ -49,6 +56,10 @@ def stream_tokens(response: str, delay: float = 0.01) -> Generator[str, None, No
|
|
| 49 |
|
| 50 |
def generate_stream(prompt: str, model: AutoModelForCausalLM, tokenizer: AutoTokenizer) -> Optional[str]:
|
| 51 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
# Format prompt with safety checks
|
| 53 |
safe_prompt = prompt.strip().replace("<", "<").replace(">", ">")
|
| 54 |
chat_prompt = f"""### Human: {safe_prompt}
|
|
@@ -124,7 +135,6 @@ def generate_stream(prompt: str, model: AutoModelForCausalLM, tokenizer: AutoTok
|
|
| 124 |
return response
|
| 125 |
|
| 126 |
except Exception as e:
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
return None
|
|
|
|
| 9 |
|
| 10 |
@st.cache_resource
|
| 11 |
def load_model():
|
| 12 |
+
if "model_loaded" not in st.session_state:
|
| 13 |
+
st.session_state.model_loaded = False
|
| 14 |
+
|
| 15 |
model_name = "deepseek-ai/Janus-Pro-7B"
|
| 16 |
|
| 17 |
try:
|
| 18 |
+
with st.spinner("🔄 Loading model (first run only)..."):
|
| 19 |
+
tokenizer = AutoTokenizer.from_pretrained(
|
| 20 |
+
model_name,
|
| 21 |
+
trust_remote_code=True,
|
| 22 |
+
padding_side='left'
|
| 23 |
+
)
|
| 24 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 25 |
+
|
| 26 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 27 |
+
model_name,
|
| 28 |
+
torch_dtype=torch.float32,
|
| 29 |
+
low_cpu_mem_usage=True,
|
| 30 |
+
trust_remote_code=True,
|
| 31 |
+
device_map='cpu'
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
model.eval()
|
| 35 |
+
torch.set_num_threads(8)
|
| 36 |
+
st.session_state.model_loaded = True
|
| 37 |
+
|
| 38 |
+
return model, tokenizer
|
| 39 |
+
|
| 40 |
except Exception as e:
|
| 41 |
+
st.error(f"❌ Error loading model: {str(e)}")
|
| 42 |
+
st.info("Try refreshing the page or clearing the cache.")
|
| 43 |
st.stop()
|
| 44 |
|
| 45 |
def stream_tokens(response: str, delay: float = 0.01) -> Generator[str, None, None]:
|
|
|
|
| 56 |
|
| 57 |
def generate_stream(prompt: str, model: AutoModelForCausalLM, tokenizer: AutoTokenizer) -> Optional[str]:
|
| 58 |
try:
|
| 59 |
+
# Safety checks
|
| 60 |
+
if not model or not tokenizer:
|
| 61 |
+
raise ValueError("Model or tokenizer not initialized")
|
| 62 |
+
|
| 63 |
# Format prompt with safety checks
|
| 64 |
safe_prompt = prompt.strip().replace("<", "<").replace(">", ">")
|
| 65 |
chat_prompt = f"""### Human: {safe_prompt}
|
|
|
|
| 135 |
return response
|
| 136 |
|
| 137 |
except Exception as e:
|
| 138 |
+
st.error(f"Generation error: {str(e)}")
|
| 139 |
+
return "I apologize, but I couldn't generate a response. Please try again."
|
| 140 |
+
```
|
|
|