Niansuh commited on
Commit
2e1595e
·
verified ·
1 Parent(s): e58fde0

Update api/utils.py

Browse files
Files changed (1) hide show
  1. api/utils.py +60 -67
api/utils.py CHANGED
@@ -3,10 +3,10 @@ import json
3
  from typing import Any, Dict, Optional
4
 
5
  import httpx
6
- import aiohttp # Add this import
7
  from api.config import (
8
- DDG_API_ENDPOINT, # Updated
9
- DDG_STATUS_URL, # Updated
10
  MODEL_MAPPING,
11
  ALLOWED_MODELS,
12
  AGENT_MODE,
@@ -23,9 +23,6 @@ import uuid
23
 
24
  logger = setup_logger(__name__)
25
 
26
- # Remove Blackbox-specific functions and add DDG-specific functions
27
-
28
- # New DDG Integration
29
  async def get_ddg_vqd():
30
  status_url = DDG_STATUS_URL
31
 
@@ -39,7 +36,10 @@ async def get_ddg_vqd():
39
  try:
40
  async with session.get(status_url, headers=headers) as response:
41
  if response.status == 200:
42
- return response.headers.get("x-vqd-4")
 
 
 
43
  else:
44
  logger.error(f"Error: Status code {response.status} when fetching VQD")
45
  return None
@@ -47,31 +47,12 @@ async def get_ddg_vqd():
47
  logger.error(f"Error getting VQD: {e}")
48
  return None
49
 
50
- def format_prompt(messages):
51
- """Helper function to format messages into a prompt string."""
52
- return "\n".join([f"{msg.role}: {msg.content}" for msg in messages])
53
-
54
- def message_to_dict_ddg(message, model_prefix: Optional[str] = None):
55
  if isinstance(message.content, str):
56
- content = message.content
57
- if model_prefix:
58
- content = f"{model_prefix} {content}"
59
- return {"role": message.role, "content": content}
60
- elif isinstance(message.content, list) and len(message.content) == 2:
61
- content = message.content[0]["text"]
62
- if model_prefix:
63
- content = f"{model_prefix} {content}"
64
- return {
65
- "role": message.role,
66
- "content": content,
67
- "data": {
68
- "imageBase64": message.content[1]["image_url"]["url"],
69
- "fileText": "",
70
- "title": "snapshot",
71
- },
72
- }
73
- else:
74
  return {"role": message.role, "content": message.content}
 
 
 
75
 
76
  def strip_model_prefix(content: str, model_prefix: Optional[str] = None) -> str:
77
  """Remove the model prefix from the response content if present."""
@@ -81,28 +62,53 @@ def strip_model_prefix(content: str, model_prefix: Optional[str] = None) -> str:
81
  logger.debug("No prefix to strip from content.")
82
  return content
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  async def process_ddg_streaming_response(request: ChatRequest):
85
  agent_mode = AGENT_MODE.get(request.model, {})
86
  trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
87
  model_prefix = MODEL_PREFIXES.get(request.model, "")
88
- referer_path = MODEL_REFERERS.get(request.model, f"/?model={request.model}")
89
- referer_url = f"https://duckduckgo.com{referer_path}" # Updated BASE_URL
 
 
 
 
90
 
91
- # Update headers with dynamic Referer
92
  dynamic_headers = {
93
  'accept': 'text/event-stream',
94
  'content-type': 'application/json',
95
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
96
- 'x-vqd-4': await get_ddg_vqd()
97
  }
98
 
99
- if not dynamic_headers['x-vqd-4']:
100
- raise HTTPException(status_code=500, detail="Failed to obtain VQD token")
 
 
 
 
101
 
102
  json_data = {
103
  "model": MODEL_MAPPING.get(request.model, request.model),
104
- "messages": [message_to_dict_ddg(msg, model_prefix=model_prefix) for msg in request.messages],
105
- # Add additional fields if required by DDG API
106
  }
107
 
108
  async with httpx.AsyncClient() as client:
@@ -121,7 +127,7 @@ async def process_ddg_streaming_response(request: ChatRequest):
121
  content = line
122
  if content.startswith("$@$v=undefined-rv1$@$"):
123
  content = content[21:]
124
- # Strip the model prefix from the response content
125
  cleaned_content = strip_model_prefix(content, model_prefix)
126
  yield f"data: {json.dumps(create_chat_completion_data(cleaned_content, request.model, timestamp))}\n\n"
127
 
@@ -138,27 +144,33 @@ async def process_ddg_non_streaming_response(request: ChatRequest):
138
  agent_mode = AGENT_MODE.get(request.model, {})
139
  trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
140
  model_prefix = MODEL_PREFIXES.get(request.model, "")
141
- referer_path = MODEL_REFERERS.get(request.model, f"/?model={request.model}")
142
- referer_url = f"https://duckduckgo.com{referer_path}" # Updated BASE_URL
 
 
 
 
143
 
144
- # Update headers with dynamic Referer
145
  dynamic_headers = {
146
  'accept': 'application/json',
147
  'content-type': 'application/json',
148
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
149
- 'x-vqd-4': await get_ddg_vqd()
150
  }
151
 
152
- if not dynamic_headers['x-vqd-4']:
153
- raise HTTPException(status_code=500, detail="Failed to obtain VQD token")
 
 
 
 
154
 
155
  json_data = {
156
  "model": MODEL_MAPPING.get(request.model, request.model),
157
- "messages": [message_to_dict_ddg(msg, model_prefix=model_prefix) for msg in request.messages],
158
- # Add additional fields if required by DDG API
159
  }
160
 
161
- full_response = ""
162
  async with httpx.AsyncClient() as client:
163
  try:
164
  response = await client.post(
@@ -179,7 +191,6 @@ async def process_ddg_non_streaming_response(request: ChatRequest):
179
  if full_response.startswith("$@$v=undefined-rv1$@$"):
180
  full_response = full_response[21:]
181
 
182
- # Strip the model prefix from the full response
183
  cleaned_full_response = strip_model_prefix(full_response, model_prefix)
184
 
185
  return {
@@ -196,21 +207,3 @@ async def process_ddg_non_streaming_response(request: ChatRequest):
196
  ],
197
  "usage": None,
198
  }
199
-
200
- def create_chat_completion_data(
201
- content: str, model: str, timestamp: int, finish_reason: Optional[str] = None
202
- ) -> Dict[str, Any]:
203
- return {
204
- "id": f"chatcmpl-{uuid.uuid4()}",
205
- "object": "chat.completion.chunk",
206
- "created": timestamp,
207
- "model": model,
208
- "choices": [
209
- {
210
- "index": 0,
211
- "delta": {"content": content, "role": "assistant"},
212
- "finish_reason": finish_reason,
213
- }
214
- ],
215
- "usage": None,
216
- }
 
3
  from typing import Any, Dict, Optional
4
 
5
  import httpx
6
+ import aiohttp
7
  from api.config import (
8
+ DDG_API_ENDPOINT,
9
+ DDG_STATUS_URL,
10
  MODEL_MAPPING,
11
  ALLOWED_MODELS,
12
  AGENT_MODE,
 
23
 
24
  logger = setup_logger(__name__)
25
 
 
 
 
26
  async def get_ddg_vqd():
27
  status_url = DDG_STATUS_URL
28
 
 
36
  try:
37
  async with session.get(status_url, headers=headers) as response:
38
  if response.status == 200:
39
+ vqd = response.headers.get("x-vqd-4")
40
+ if not vqd:
41
+ logger.error("VQD token not found in response headers.")
42
+ return vqd
43
  else:
44
  logger.error(f"Error: Status code {response.status} when fetching VQD")
45
  return None
 
47
  logger.error(f"Error getting VQD: {e}")
48
  return None
49
 
50
+ def message_to_dict_ddg(message):
 
 
 
 
51
  if isinstance(message.content, str):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  return {"role": message.role, "content": message.content}
53
+ else:
54
+ # If DDG API does not support non-string content, raise an error
55
+ raise ValueError("Message content must be a string.")
56
 
57
  def strip_model_prefix(content: str, model_prefix: Optional[str] = None) -> str:
58
  """Remove the model prefix from the response content if present."""
 
62
  logger.debug("No prefix to strip from content.")
63
  return content
64
 
65
+ def create_chat_completion_data(
66
+ content: str, model: str, timestamp: int, finish_reason: Optional[str] = None
67
+ ) -> Dict[str, Any]:
68
+ return {
69
+ "id": f"chatcmpl-{uuid.uuid4()}",
70
+ "object": "chat.completion.chunk",
71
+ "created": timestamp,
72
+ "model": model,
73
+ "choices": [
74
+ {
75
+ "index": 0,
76
+ "delta": {"content": content, "role": "assistant"},
77
+ "finish_reason": finish_reason,
78
+ }
79
+ ],
80
+ "usage": None,
81
+ }
82
+
83
  async def process_ddg_streaming_response(request: ChatRequest):
84
  agent_mode = AGENT_MODE.get(request.model, {})
85
  trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
86
  model_prefix = MODEL_PREFIXES.get(request.model, "")
87
+ # referer_path and referer_url are not required unless specified by DDG API
88
+
89
+ # Obtain VQD token
90
+ vqd = await get_ddg_vqd()
91
+ if not vqd:
92
+ raise HTTPException(status_code=500, detail="Failed to obtain VQD token")
93
 
94
+ # Build headers
95
  dynamic_headers = {
96
  'accept': 'text/event-stream',
97
  'content-type': 'application/json',
98
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
99
+ 'x-vqd-4': vqd
100
  }
101
 
102
+ # Construct message history
103
+ try:
104
+ message_history = [message_to_dict_ddg(msg) for msg in request.messages]
105
+ except ValueError as ve:
106
+ logger.error(f"Invalid message format: {ve}")
107
+ raise HTTPException(status_code=400, detail=str(ve))
108
 
109
  json_data = {
110
  "model": MODEL_MAPPING.get(request.model, request.model),
111
+ "messages": message_history,
 
112
  }
113
 
114
  async with httpx.AsyncClient() as client:
 
127
  content = line
128
  if content.startswith("$@$v=undefined-rv1$@$"):
129
  content = content[21:]
130
+ # No model_prefix handling as messages are correctly formatted
131
  cleaned_content = strip_model_prefix(content, model_prefix)
132
  yield f"data: {json.dumps(create_chat_completion_data(cleaned_content, request.model, timestamp))}\n\n"
133
 
 
144
  agent_mode = AGENT_MODE.get(request.model, {})
145
  trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
146
  model_prefix = MODEL_PREFIXES.get(request.model, "")
147
+ # referer_path and referer_url are not required unless specified by DDG API
148
+
149
+ # Obtain VQD token
150
+ vqd = await get_ddg_vqd()
151
+ if not vqd:
152
+ raise HTTPException(status_code=500, detail="Failed to obtain VQD token")
153
 
154
+ # Build headers
155
  dynamic_headers = {
156
  'accept': 'application/json',
157
  'content-type': 'application/json',
158
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
159
+ 'x-vqd-4': vqd
160
  }
161
 
162
+ # Construct message history
163
+ try:
164
+ message_history = [message_to_dict_ddg(msg) for msg in request.messages]
165
+ except ValueError as ve:
166
+ logger.error(f"Invalid message format: {ve}")
167
+ raise HTTPException(status_code=400, detail=str(ve))
168
 
169
  json_data = {
170
  "model": MODEL_MAPPING.get(request.model, request.model),
171
+ "messages": message_history,
 
172
  }
173
 
 
174
  async with httpx.AsyncClient() as client:
175
  try:
176
  response = await client.post(
 
191
  if full_response.startswith("$@$v=undefined-rv1$@$"):
192
  full_response = full_response[21:]
193
 
 
194
  cleaned_full_response = strip_model_prefix(full_response, model_prefix)
195
 
196
  return {
 
207
  ],
208
  "usage": None,
209
  }