code-slicer commited on
Commit
c8b7d5d
Β·
verified Β·
1 Parent(s): fb4e4fe

Create llm_ollama.py

Browse files
Files changed (1) hide show
  1. llm_ollama.py +87 -0
llm_ollama.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # llm_ollama.py νŒŒμΌμ— λ‹€μŒ λ‚΄μš©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
2
+ import json
3
+ import requests
4
+ import streamlit as st
5
+
6
+ OLLAMA_HOST = "http://localhost:11434"
7
+ OLLAMA_MODEL = "gemma2:9b"
8
+ OLLAMA_TIMEOUT = 60
9
+
10
+ KOREAN_SYSTEM_PROMPT = """당신은 ν•œκ΅­μ–΄ μ–΄μ‹œμŠ€ν„΄νŠΈμž…λ‹ˆλ‹€. 항상 ν•œκ΅­μ–΄λ‘œ λ‹΅ν•˜μ„Έμš”."""
11
+ STRUCTURED_EXTRACTION_SYSTEM = """\
12
+ You are a travel assistant that extracts structured fields from Korean user queries.
13
+ Return ONLY a valid JSON object:
14
+ {
15
+ "emotion": "happy|sad|stressed|excited|tired|none",
16
+ "intent": "beach|hiking|shopping|food|museum|relaxing|none",
17
+ "country_hint": "",
18
+ "city_hint": "",
19
+ "themes_hint": ["<0..3 words>"],
20
+ "notes": "<very short reasoning in Korean>"
21
+ }
22
+ If unknown, use "none" or "" and NEVER add extra text outside JSON.
23
+ """
24
+
25
+ def _call_ollama_chat(messages, model=OLLAMA_MODEL,
26
+ temperature=0.8, top_p=0.9, top_k=40, repeat_penalty=1.1,
27
+ system_prompt=None):
28
+ url = f"{OLLAMA_HOST}/api/chat"
29
+ _msgs = []
30
+ if system_prompt:
31
+ _msgs.append({"role":"system","content":system_prompt})
32
+ _msgs.extend(messages)
33
+ payload = {
34
+ "model": model,
35
+ "messages": _msgs,
36
+ "options": {
37
+ "temperature": temperature,
38
+ "top_p": top_p,
39
+ "top_k": top_k,
40
+ "repeat_penalty": repeat_penalty,
41
+ },
42
+ "stream": False,
43
+ }
44
+ try:
45
+ r = requests.post(url, json=payload, timeout=OLLAMA_TIMEOUT)
46
+ r.raise_for_status()
47
+ return (r.json().get("message") or {}).get("content","") or ""
48
+ except requests.RequestException:
49
+ return ""
50
+
51
+ def llm_followup_loop():
52
+ # Streamlit은 맀번 μƒˆλ‘œ μ‹€ν–‰λ˜λ―€λ‘œ, λŒ€ν™” 기둝을 μ„Έμ…˜ μƒνƒœμ— μ €μž₯ν•΄μ•Ό 함
53
+ if "llm_history" not in st.session_state:
54
+ st.session_state.llm_history = [{"role": "bot", "content": "μ–΄λ–€ 점이 더 κΆκΈˆν•˜μ‹ κ°€μš”?"}]
55
+
56
+ # μ±— λ©”μ‹œμ§€ 기둝
57
+ for message in st.session_state.llm_history:
58
+ with st.chat_message(message["role"]):
59
+ st.markdown(message["content"])
60
+
61
+ # μ‚¬μš©μž μž…λ ₯ λ°›κΈ°
62
+ q = st.chat_input("여행에 λŒ€ν•΄ 더 κΆκΈˆν•œ 점이 μžˆλ‚˜μš”?")
63
+
64
+ if q:
65
+ # μ‚¬μš©μž λ©”μ‹œμ§€ ν‘œμ‹œ 및 기둝
66
+ st.session_state.llm_history.append({"role": "user", "content": q})
67
+ with st.chat_message("user"):
68
+ st.markdown(q)
69
+
70
+ # Ollama API 호좜
71
+ with st.spinner("생각 쀑..."):
72
+ messages = [{"role": m["role"], "content": m["content"]} for m in st.session_state.llm_history]
73
+
74
+ a = _call_ollama_chat(
75
+ messages,
76
+ system_prompt=KOREAN_SYSTEM_PROMPT,
77
+ temperature=0.8, top_p=0.9, top_k=40, repeat_penalty=1.1
78
+ )
79
+
80
+ # 봇 λ©”μ‹œμ§€ ν‘œμ‹œ 및 기둝
81
+ if not a:
82
+ st.session_state.llm_history.append({"role": "assistant", "content": "⚠️ Ollama 응닡을 λ°›μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. μ„œλ²„ μƒνƒœλ₯Ό ν™•μΈν•˜μ„Έμš”."})
83
+ else:
84
+ st.session_state.llm_history.append({"role": "assistant", "content": a})
85
+
86
+ # νŽ˜μ΄μ§€ λ¦¬λ‘œλ“œ
87
+ st.rerun()