Repository navigation
Expand file tree
/
Copy pathanswer.py
More file actions
95 lines (90 loc) · 4.31 KB
/
Copy pathanswer.py
File metadata and controls
95 lines (90 loc) · 4.31 KB
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
import os
from dotenv import load_dotenv
load_dotenv()
import json
from openai import OpenAI
import chromadb
client = OpenAI(
base_url="https://ai.hackclub.com/proxy/v1",
api_key= os.environ.get("HACKCLUB_AI_KEY")
)
chroma_client = chromadb.PersistentClient(path="./db")
collection = chroma_client.get_or_create_collection(name="messages")
with open("trusted_users.json", "r") as f:
trusted_users = json.load(f)
def is_trusted(user_id, channel_id):
if user_id in trusted_users.get("global", []):
return True
if user_id in trusted_users.get("channel_id", []):
return True
return False
#def is_question(text):
# response = client.chat.completions.create(
# model="openai/gpt-4o-mini",
# messages=[
# {
# "role": "system",
# "content": """You are a question detector. Respond with only YES or NO. Reply YES if the message is asking for information, clarification, or help understanding something. Reply NO if it is a statement, reaction, greeting, or casual comment."""},
# {
# "role": "user",
# "content": text
# }
# ],
# max_tokens = 100
# )
# result = (response.choices[0].message.content or "NO")
# print(f"RAW: '{result}'")
#return "YES" in result.upper()
def answer_question(question):
embedding_response = client.embeddings.create(model="openai/text-embedding-3-small", input=question)
question_vector = embedding_response.data[0].embedding
results = collection.query(query_embeddings=[question_vector], n_results=5)
matched_messages = results["documents"][0]
matched_metadata = results["metadatas"][0]
most_recent = max(
zip(matched_messages, matched_metadata),
key=lambda x: float(x[1]["ts"])
)
most_recent_text = most_recent[0]
most_recent_meta = most_recent[1]
context = "\n\n".join([f"Message (ts: {meta['ts']}): {text}" for text, meta in zip(matched_messages, matched_metadata)])
chat_response = client.chat.completions.create(model="qwen/qwen3-32b", messages=[
{"role": "system",
"content": """You are a friendly and professional Hack Club support assistant. Answer questions warmly and directly, as if you're a knowledgeable team member who genuinely wants to help. Keep your tone conversational, approachable, and encouraging — like a helpful person on a support team, not a robot. Never mention that you have access to messages, context, documents, or any data source. Never reference timestamps, IDs, or any internal system. Just answer naturally and confidently as if you already know this information. If you're not confident in the answer, say so kindly and suggest the person reach out to the Hack Club team directly. Keep your answers concise — no more than 3-4 sentences unless the question genuinely requires more detail."""},
{"role": "user",
"content": f"Context from Hack Club Slack:\n\n{context}\n\nQuestion: {question}"}
]
)
answer = chat_response.choices[0].message.content
if "NO_ANSWER" in answer.upper():
return None
return {
"answer": answer,
"source_ts": most_recent_meta["ts"],
"source_user": most_recent_meta["user"],
"based_on_trusted_source": is_trusted(most_recent_meta["user"], most_recent_meta["channel"])
}
if __name__ == "__main__":
test_question = "What is resolution?"
print(f"Question: {test_question}\n")
result = answer_question(test_question)
if result == None:
print("Bot stayed silent - no relevant answer found")
else:
print(f"Answer: {result['answer']}\n")
print(f"Based on trusted source: {result['based_on_trusted_source']}")
print(f"Most recent source timestamp: {result['source_ts']}")
#print(is_question("How do gap year stipends work?"))
#print(is_question("lol that's hilarious"))
#raw = client.chat.completions.create(model="openai/gpt-4o-mini", messages=[
# {
# "role": "system",
# "content": "Reply with only YES or NO."
# },
# {
# "role": "user",
# "content": "How do gap year stipends work?"
# }
#], max_tokens=10)
#print(f"Raw response object: {raw}")
#print(f"Content: {raw.choices[0].message.content}")