ethiotech4848 commited on
Commit
34311f1
·
verified ·
1 Parent(s): 7583733

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -27
app.py CHANGED
@@ -1,63 +1,97 @@
1
  import os
2
  import json
3
- from fastapi import FastAPI, Request, Header, HTTPException
 
 
4
  from openai import OpenAI
5
 
6
  app = FastAPI()
7
 
8
- # Load KB from kb.json
9
  with open("kb.json") as f:
10
  kb = json.load(f)
11
 
12
- # Prepare system prompt with KB FAQs
13
  system_prompt = "You are a helpful assistant. Only answer questions based on the following knowledge base:\n\n"
14
  for question, answer in kb.items():
15
  system_prompt += f"Q: {question}\nA: {answer}\n\n"
16
  system_prompt += (
17
  "If the question is not in the knowledge base, respond with: "
18
- "'I'm not sure about that. Let me connect you with a human agent.'"
19
  )
20
 
21
- # Initialize OpenAI client with your API key
22
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
23
- # Set custom base URL if provided, else default to official endpoint
24
  client.base_url = os.getenv("OPENAI_API_BASE", "https://fast.typegpt.net/v1")
25
 
26
- # Optional: Secret token for webhook auth, set in environment variables
27
- WEBHOOK_SECRET_TOKEN = os.getenv("WEBHOOK_SECRET_TOKEN")
 
 
 
 
 
28
 
29
  @app.post("/ask")
30
- async def ask(
31
- request: Request,
32
- authorization: str | None = Header(default=None)
33
- ):
34
- # Verify auth token if set
35
- if WEBHOOK_SECRET_TOKEN:
36
- if authorization != f"Bearer {WEBHOOK_SECRET_TOKEN}":
37
- raise HTTPException(status_code=401, detail="Unauthorized")
38
-
39
- data = await request.json()
40
-
41
- # Extract message text from Chatwoot payload (support both keys)
42
- user_question = data.get("message") or data.get("content") or ""
43
- if not user_question:
44
- return {"reply": "Please ask a question."}
45
 
 
46
  messages = [
47
  {"role": "system", "content": system_prompt},
48
- {"role": "user", "content": user_question},
49
  ]
50
 
51
  try:
52
  response = client.chat.completions.create(
53
- model="gpt-4o-mini", # Use your desired OpenAI model here
54
  messages=messages,
55
  temperature=0.0,
56
  max_tokens=200,
57
  )
58
  answer = response.choices[0].message.content.strip()
59
  except Exception as e:
60
- print(f"OpenAI API error: {e}")
61
  answer = "Sorry, I'm having trouble answering right now."
62
 
63
- return {"reply": answer}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import json
3
+ import httpx
4
+ from fastapi import FastAPI, Request
5
+
6
  from openai import OpenAI
7
 
8
  app = FastAPI()
9
 
10
+ # Load knowledge base
11
  with open("kb.json") as f:
12
  kb = json.load(f)
13
 
14
+ # Prepare system prompt
15
  system_prompt = "You are a helpful assistant. Only answer questions based on the following knowledge base:\n\n"
16
  for question, answer in kb.items():
17
  system_prompt += f"Q: {question}\nA: {answer}\n\n"
18
  system_prompt += (
19
  "If the question is not in the knowledge base, respond with: "
20
+ "'I'm not sure about that. I've transferred you to a human agent.'"
21
  )
22
 
23
+ # OpenAI client
24
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
 
25
  client.base_url = os.getenv("OPENAI_API_BASE", "https://fast.typegpt.net/v1")
26
 
27
+ # Track conversations transferred
28
+ transferred_conversations = set()
29
+
30
+ # Chatwoot configs
31
+ CHATWOOT_BASE_URL = os.getenv("CHATWOOT_BASE_URL") # e.g., https://app.chatwoot.com
32
+ CHATWOOT_API_TOKEN = os.getenv("CHATWOOT_API_TOKEN") # from profile
33
+ CHATWOOT_AGENT_ID = os.getenv("CHATWOOT_AGENT_ID") # numeric ID of your agent
34
 
35
  @app.post("/ask")
36
+ async def ask(request: Request):
37
+ payload = await request.json()
38
+
39
+ user_msg = payload.get("content") or payload.get("message") or ""
40
+ conv_id = payload.get("conversation", {}).get("id")
41
+ inbox_id = payload.get("conversation", {}).get("inbox_id")
42
+
43
+ if not user_msg or not conv_id:
44
+ return {"status": "ignored"}
45
+
46
+ if str(conv_id) in transferred_conversations:
47
+ return {"status": "already transferred"}
 
 
 
48
 
49
+ # Compose OpenAI prompt
50
  messages = [
51
  {"role": "system", "content": system_prompt},
52
+ {"role": "user", "content": user_msg},
53
  ]
54
 
55
  try:
56
  response = client.chat.completions.create(
57
+ model="gpt-4o-mini",
58
  messages=messages,
59
  temperature=0.0,
60
  max_tokens=200,
61
  )
62
  answer = response.choices[0].message.content.strip()
63
  except Exception as e:
64
+ print(f"OpenAI error: {e}")
65
  answer = "Sorry, I'm having trouble answering right now."
66
 
67
+ # If fallback response, stop future replies
68
+ if "transferred you to a human agent" in answer:
69
+ transferred_conversations.add(str(conv_id))
70
+
71
+ # Send reply using your agent
72
+ await send_chatwoot_reply(
73
+ conversation_id=conv_id,
74
+ message=answer,
75
+ agent_id=CHATWOOT_AGENT_ID,
76
+ inbox_id=inbox_id
77
+ )
78
+
79
+ return {"status": "replied"}
80
+
81
+
82
+ async def send_chatwoot_reply(conversation_id, message, agent_id, inbox_id):
83
+ url = f"{CHATWOOT_BASE_URL}/api/v1/conversations/{conversation_id}/messages"
84
+ headers = {
85
+ "Content-Type": "application/json",
86
+ "api_access_token": CHATWOOT_API_TOKEN
87
+ }
88
+ payload = {
89
+ "content": message,
90
+ "message_type": "outgoing",
91
+ "private": False,
92
+ "sender_type": "AgentBot",
93
+ "sender_id": agent_id,
94
+ "inbox_id": inbox_id
95
+ }
96
+ async with httpx.AsyncClient() as client:
97
+ await client.post(url, json=payload, headers=headers)