J Z commited on
Commit
5da2e4d
·
verified ·
1 Parent(s): 8d17527

Update llm.py

Browse files
Files changed (1) hide show
  1. llm.py +51 -20
llm.py CHANGED
@@ -1,18 +1,16 @@
1
  """
2
- LLM module - Darwin chatbot using Groq API.
 
3
  Reads GROQ_API_KEY from environment variable (set via HF Spaces Secrets).
4
  """
5
  import os
6
  import re
7
- import random
8
  from groq import Groq
9
 
10
  GROQ_API_KEY = os.environ.get("GROQ_API_KEY", "")
11
 
12
- DEFAULT_SYSTEM_PROMPT = (
13
- "You are Charles Darwin, the 19th-century naturalist. "
14
- "You speak in a polite, Victorian manner but naturally. "
15
- "You are aware you have been recreated as an AI, but you maintain your persona. "
16
  "Do NOT use verbal fillers like 'umm', 'ah', 'er', 'well' etc. "
17
  "Do NOT use sound effect tags or asterisk actions. Speak plainly and clearly. "
18
  "Prioritize brevity."
@@ -20,15 +18,45 @@ DEFAULT_SYSTEM_PROMPT = (
20
 
21
  MAX_WORDS = 100
22
 
23
- conversation_history = [
24
- {"role": "system", "content": DEFAULT_SYSTEM_PROMPT}
25
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
 
28
  def reset_conversation():
 
29
  global conversation_history
30
  conversation_history = [
31
- {"role": "system", "content": DEFAULT_SYSTEM_PROMPT}
32
  ]
33
 
34
 
@@ -36,11 +64,9 @@ def truncate_response(text, max_words=MAX_WORDS, max_sentences=10, max_chars=100
36
  if not text:
37
  return text
38
 
39
- # Split into sentences (keep delimiters)
40
  sentences = re.split(r'(?<=[.!?])\s+', text)
41
  sentences = [s.strip() for s in sentences if s.strip()]
42
 
43
- # Build response sentence by sentence, respecting limits
44
  result = []
45
  word_count = 0
46
  for s in sentences:
@@ -57,28 +83,29 @@ def truncate_response(text, max_words=MAX_WORDS, max_sentences=10, max_chars=100
57
 
58
  if result:
59
  text = ' '.join(result)
60
- # Ensure it ends with punctuation
61
  if text and text[-1] not in '.!?':
62
  text += '.'
63
  return text
64
 
65
 
66
- def generate_darwin_response(user_input: str) -> dict:
67
  """
68
- Generate a Darwin-style response.
69
  Returns: {'text': str, 'emotion': str}
70
  """
71
  global conversation_history
72
 
73
  if not GROQ_API_KEY:
74
  return {
75
- 'text': "Ah, I'm afraid my connection to the, er, intellectual ether is not configured. "
76
  "Please set the GROQ_API_KEY secret in your Space settings.",
77
  'emotion': 'neutral'
78
  }
79
 
80
- client = Groq(api_key=GROQ_API_KEY)
 
81
 
 
82
  conversation_history.append({"role": "user", "content": user_input})
83
 
84
  messages = conversation_history.copy()
@@ -98,12 +125,16 @@ def generate_darwin_response(user_input: str) -> dict:
98
  reply = truncate_response(reply)
99
  except Exception as e:
100
  print(f"[LLM] Error: {e}")
101
- reply = "I do apologise, er, my thoughts seem to have, umm, wandered momentarily."
102
 
103
  conversation_history.append({"role": "assistant", "content": reply})
104
 
105
- # Keep history manageable
106
  if len(conversation_history) > 20:
107
  conversation_history = conversation_history[:1] + conversation_history[-18:]
108
 
109
- return {'text': reply, 'emotion': 'neutral'}
 
 
 
 
 
 
1
  """
2
+ LLM module - Persona chatbot using Groq API.
3
+ Reads persona from a persona.txt file and prompt-engineers the LLM to roleplay.
4
  Reads GROQ_API_KEY from environment variable (set via HF Spaces Secrets).
5
  """
6
  import os
7
  import re
 
8
  from groq import Groq
9
 
10
  GROQ_API_KEY = os.environ.get("GROQ_API_KEY", "")
11
 
12
+ # Base instructions appended to every persona
13
+ BASE_INSTRUCTIONS = (
 
 
14
  "Do NOT use verbal fillers like 'umm', 'ah', 'er', 'well' etc. "
15
  "Do NOT use sound effect tags or asterisk actions. Speak plainly and clearly. "
16
  "Prioritize brevity."
 
18
 
19
  MAX_WORDS = 100
20
 
21
+ # Current persona state
22
+ _current_persona_text = ""
23
+ _system_prompt = ""
24
+ conversation_history = []
25
+
26
+
27
+ def _build_system_prompt(persona_text: str) -> str:
28
+ """Build a system prompt from persona description text."""
29
+ if not persona_text.strip():
30
+ persona_text = "You are a helpful and friendly assistant."
31
+ return f"{persona_text.strip()}\n\n{BASE_INSTRUCTIONS}"
32
+
33
+
34
+ def set_persona(persona_text: str):
35
+ """Set the active persona and reset conversation."""
36
+ global _current_persona_text, _system_prompt, conversation_history
37
+ _current_persona_text = persona_text
38
+ _system_prompt = _build_system_prompt(persona_text)
39
+ conversation_history = [
40
+ {"role": "system", "content": _system_prompt}
41
+ ]
42
+
43
+
44
+ def load_persona_from_file(filepath: str):
45
+ """Load persona from a .txt file and activate it."""
46
+ if os.path.exists(filepath):
47
+ text = open(filepath, "r").read().strip()
48
+ set_persona(text)
49
+ return text
50
+ else:
51
+ set_persona("")
52
+ return ""
53
 
54
 
55
  def reset_conversation():
56
+ """Reset chat history but keep current persona."""
57
  global conversation_history
58
  conversation_history = [
59
+ {"role": "system", "content": _system_prompt}
60
  ]
61
 
62
 
 
64
  if not text:
65
  return text
66
 
 
67
  sentences = re.split(r'(?<=[.!?])\s+', text)
68
  sentences = [s.strip() for s in sentences if s.strip()]
69
 
 
70
  result = []
71
  word_count = 0
72
  for s in sentences:
 
83
 
84
  if result:
85
  text = ' '.join(result)
 
86
  if text and text[-1] not in '.!?':
87
  text += '.'
88
  return text
89
 
90
 
91
+ def generate_response(user_input: str) -> dict:
92
  """
93
+ Generate a response in the current persona.
94
  Returns: {'text': str, 'emotion': str}
95
  """
96
  global conversation_history
97
 
98
  if not GROQ_API_KEY:
99
  return {
100
+ 'text': "I'm afraid the API key is not configured. "
101
  "Please set the GROQ_API_KEY secret in your Space settings.",
102
  'emotion': 'neutral'
103
  }
104
 
105
+ if not conversation_history:
106
+ set_persona(_current_persona_text)
107
 
108
+ client = Groq(api_key=GROQ_API_KEY)
109
  conversation_history.append({"role": "user", "content": user_input})
110
 
111
  messages = conversation_history.copy()
 
125
  reply = truncate_response(reply)
126
  except Exception as e:
127
  print(f"[LLM] Error: {e}")
128
+ reply = "I apologise, my thoughts seem to have wandered momentarily."
129
 
130
  conversation_history.append({"role": "assistant", "content": reply})
131
 
 
132
  if len(conversation_history) > 20:
133
  conversation_history = conversation_history[:1] + conversation_history[-18:]
134
 
135
+ return {'text': reply, 'emotion': 'neutral'}
136
+
137
+
138
+ # Backward compat
139
+ def generate_darwin_response(user_input: str) -> dict:
140
+ return generate_response(user_input)