comprobot 1.1.2__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/functions.py +96 -63
  2. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/main.py +2 -2
  3. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/templates.py +25 -1
  4. {comprobot-1.1.2/comprobot.egg-info → comprobot-1.2.0}/PKG-INFO +1 -1
  5. {comprobot-1.1.2 → comprobot-1.2.0/comprobot.egg-info}/PKG-INFO +1 -1
  6. {comprobot-1.1.2 → comprobot-1.2.0}/pyproject.toml +1 -1
  7. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/__init__.py +0 -0
  8. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/__main__.py +0 -0
  9. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/api.py +0 -0
  10. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/bot.py +0 -0
  11. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/commands.py +0 -0
  12. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/data.py +0 -0
  13. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/moderation.py +0 -0
  14. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/money_system.py +0 -0
  15. {comprobot-1.1.2 → comprobot-1.2.0}/Comprobot/process.py +0 -0
  16. {comprobot-1.1.2 → comprobot-1.2.0}/README.md +0 -0
  17. {comprobot-1.1.2 → comprobot-1.2.0}/comprobot.egg-info/SOURCES.txt +0 -0
  18. {comprobot-1.1.2 → comprobot-1.2.0}/comprobot.egg-info/dependency_links.txt +0 -0
  19. {comprobot-1.1.2 → comprobot-1.2.0}/comprobot.egg-info/entry_points.txt +0 -0
  20. {comprobot-1.1.2 → comprobot-1.2.0}/comprobot.egg-info/requires.txt +0 -0
  21. {comprobot-1.1.2 → comprobot-1.2.0}/comprobot.egg-info/top_level.txt +0 -0
  22. {comprobot-1.1.2 → comprobot-1.2.0}/setup.cfg +0 -0
@@ -12,6 +12,8 @@ from google.genai.errors import ClientError
12
12
  from .bot import client
13
13
  from .data import ai, system_prompt_text
14
14
 
15
+ context_memory: Dict[int, List[Dict[str, Any]]] = {}
16
+
15
17
 
16
18
  def para(count=1):
17
19
  for i in range(count):
@@ -61,58 +63,102 @@ def demoji(text):
61
63
  return emoji_pattern.sub("", text)
62
64
 
63
65
 
64
- def chat(message):
65
- messages: List[Dict[str, Any]] = []
66
- user_id = client.user.id if client.user else ""
66
+ async def get_referenced_message(message):
67
+ if not message.reference:
68
+ return None
69
+
70
+ if isinstance(message.reference.resolved, discord.Message):
71
+ return message.reference.resolved
72
+
73
+ try:
74
+ return await message.channel.fetch_message(message.reference.message_id)
75
+ except discord.NotFound:
76
+ return None
77
+
67
78
 
68
- if ai["provider"].lower() in ("ollama", "groq"):
69
- messages.append(
70
- {
71
- "role": "user",
72
- "content": message.content.replace(f"<@{user_id}>", ""),
73
- }
79
+ async def chat(message):
80
+ user_id = client.user.id if client.user else ""
81
+ channel_id = message.channel.id
82
+
83
+ if channel_id not in context_memory:
84
+ context_memory[channel_id] = []
85
+
86
+ messages = context_memory[channel_id]
87
+
88
+ referenced_message = await get_referenced_message(message)
89
+
90
+ # Construct user content based on templates
91
+ attachment_url = ""
92
+ if message.attachments and ai["include_attachment"]:
93
+ attachment_url = message.attachments[0].url
94
+ elif referenced_message and ai["include_attachment"]:
95
+ if referenced_message.attachments:
96
+ attachment_url = referenced_message.attachments[0].url
97
+
98
+ user_prompt_content = (
99
+ ai["user_prompt_structure"]
100
+ .replace("{{PROMPT}}", ai["user_prompt"])
101
+ .replace(
102
+ "{{REPLY_PROMPT}}",
103
+ ai["user_reply_prompt"]
104
+ if ai["include_reply"] and referenced_message
105
+ else "",
74
106
  )
75
- elif ai["provider"].lower() == "gemini":
76
- messages.append(
77
- {
78
- "role": "user",
79
- "parts": [{"text": message.content.replace(f"<@{user_id}>", "")}],
80
- }
107
+ .replace(
108
+ "{{ATTACHMENT_PROMPT}}",
109
+ ai["user_attachement_prompt"].replace("{{FILE}}", attachment_url)
110
+ if attachment_url
111
+ else "",
81
112
  )
82
- else:
83
- raise ValueError(f"Unknown provider: {ai['provider']}")
113
+ .replace(
114
+ "{{USERNAME}}",
115
+ message.author.display_name if ai["include_username"] else "",
116
+ )
117
+ .replace("{{MESSAGE}}", message.content.replace(f"<@{user_id}>", ""))
118
+ .replace(
119
+ "{{REPLY}}",
120
+ referenced_message.content
121
+ if referenced_message and ai["include_reply"]
122
+ else "",
123
+ )
124
+ )
84
125
 
85
- if ai["provider"].lower() == "ollama":
86
- messages.insert(
87
- 0,
88
- {
89
- "role": "system",
90
- "content": system_prompt_text,
91
- },
126
+ # Add user message to history
127
+ messages.append({"role": "user", "content": user_prompt_content})
128
+
129
+ # Limit context
130
+ max_total = cast(int, ai["max_messages_context"])
131
+ while len(messages) > max_total:
132
+ messages.pop(0)
133
+
134
+ provider = ai["provider"].lower()
135
+ content = ""
136
+
137
+ if provider == "ollama":
138
+ formatted_messages = [
139
+ {"role": "system", "content": system_prompt_text}
140
+ ] + messages
141
+ response = ollama.chat(
142
+ model=cast(str, ai["model"]), messages=formatted_messages
92
143
  )
93
- response = ollama.chat(model=cast(str, ai["model"]), messages=messages)
94
- content: str = response.message.content or ""
95
- elif ai["provider"].lower() == "gemini":
144
+ content = response.message.content or ""
145
+ elif provider == "gemini":
96
146
  gemini_client = genai.Client(api_key=os.getenv("GEMINI"))
97
- system_instruction = None
98
147
  formatted_messages = []
99
148
  for m in messages:
100
- if m["role"] == "system":
101
- system_instruction = m["content"]
102
- else:
103
- formatted_messages.append(
104
- {
105
- "role": m["role"],
106
- "parts": [
107
- {"text": m["content"] if "content" in m else m["parts"][0]}
108
- ],
109
- }
110
- )
149
+ formatted_messages.append(
150
+ {
151
+ "role": "user" if m["role"] == "user" else "model",
152
+ "parts": [{"text": m["content"]}],
153
+ }
154
+ )
155
+
111
156
  config = None
112
- if system_instruction:
157
+ if system_prompt_text:
113
158
  config = genai.types.GenerateContentConfig(
114
- system_instruction=system_instruction
159
+ system_instruction=system_prompt_text
115
160
  )
161
+
116
162
  try:
117
163
  response = gemini_client.models.generate_content(
118
164
  model=ai["model"], contents=formatted_messages, config=config
@@ -123,38 +169,25 @@ def chat(message):
123
169
  available = gemini_client.models.list()
124
170
  print(f"Available models: {[m.name for m in available]}")
125
171
  raise
126
- elif ai["provider"].lower() == "groq":
172
+ elif provider == "groq":
127
173
  groq_client = groq.Groq(api_key=os.getenv("GROQ"))
128
174
  formatted_messages = [
129
- {"role": "system", "content": system_prompt_text},
130
- messages[0],
131
- ]
175
+ {"role": "system", "content": system_prompt_text}
176
+ ] + messages
132
177
  response = groq_client.chat.completions.create(
133
- model=ai["model"], messages=formatted_messages
178
+ model=ai["model"],
179
+ messages=formatted_messages, # type: ignore
134
180
  )
135
181
  content = response.choices[0].message.content or ""
136
182
  else:
137
183
  raise ValueError(f"Unknown provider: {ai['provider']}")
138
184
 
139
- if ai["provider"].lower() == "groq":
140
- role = "assistant"
141
- elif ai["provider"].lower() == "ollama":
142
- role = "assistant"
143
- elif ai["provider"].lower() == "gemini":
144
- role = "model"
145
- else:
146
- raise ValueError(f"Unknown provider: {ai['provider']}")
147
-
148
- messages.append(
149
- {
150
- "role": role,
151
- "content": content,
152
- }
153
- )
185
+ # Add assistant message to history
186
+ messages.append({"role": "assistant", "content": content})
154
187
 
155
- max_total = 1 + cast(int, ai["max_messages_context"])
188
+ # Prune again after adding assistant message
156
189
  while len(messages) > max_total:
157
- messages.pop(1)
190
+ messages.pop(0)
158
191
 
159
192
  if ai["remove_emojis"]:
160
193
  content = demoji(content)
@@ -66,11 +66,11 @@ async def on_message(message):
66
66
 
67
67
  if (
68
68
  f"<@{user_id}>" in message.content
69
- or (is_reply_to_bot if config["answer_to_reply"] else False)
69
+ or (is_reply_to_bot if ai["answer_to_reply"] else False)
70
70
  and ai["activate_ai"]
71
71
  ):
72
72
  async with message.channel.typing():
73
- response = chat(message)
73
+ response = await chat(message)
74
74
 
75
75
  if response:
76
76
  async with message.channel.typing():
@@ -6,11 +6,35 @@ max_messages_context = 10
6
6
  remove_emojis = true
7
7
  lower_response = true
8
8
  answer_to_reply = false
9
+ include_username = true
10
+ include_reply = true
11
+ include_attachment = true
9
12
 
10
13
  system_prompt = """
11
14
  You are a helpful assistant that gives short, helpful answers.
12
15
  Your answers can maximally be 1000 characters long.
13
- """'''
16
+ """
17
+
18
+ user_prompt = """
19
+ {{USERNAME}} wrote the following message: {{MESSAGE}}
20
+ """
21
+
22
+ user_reply_prompt = """
23
+ They added the following context: {{REPLY}}
24
+ """
25
+
26
+ user_attachement_prompt = """
27
+ The user attached the following file: {{FILE}}
28
+ """
29
+
30
+ user_prompt_structure = """
31
+ {{PROMPT}}
32
+
33
+ {{REPLY_PROMPT}}
34
+
35
+ {{ATTACHMENT_PROMPT}}
36
+ """
37
+ '''
14
38
 
15
39
  config = r"""
16
40
  command_prefix = "!"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comprobot
3
- Version: 1.1.2
3
+ Version: 1.2.0
4
4
  Summary: A self-hostable Discord bot built for maximum customization.
5
5
  Author: badluma
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comprobot
3
- Version: 1.1.2
3
+ Version: 1.2.0
4
4
  Summary: A self-hostable Discord bot built for maximum customization.
5
5
  Author: badluma
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "comprobot"
7
- version = "1.1.2"
7
+ version = "1.2.0"
8
8
  authors = [{name = "badluma"}]
9
9
  description = "A self-hostable Discord bot built for maximum customization."
10
10
  readme = "README.md"
File without changes
File without changes
File without changes
File without changes
File without changes