rkihacker commited on
Commit
9012b35
·
verified ·
1 Parent(s): 8b10794

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +125 -53
main.py CHANGED
@@ -1,91 +1,163 @@
1
- from fastapi import FastAPI, HTTPException
2
- from pydantic import BaseModel
3
  import httpx
4
  import os
 
5
 
6
  # --- Configuration ---
7
- # In a real application, use a proper search API and manage keys securely.
8
- # For this example, we'll use a placeholder.
 
9
  SEARCH_API_URL = "https://rkihacker-brave.hf.space/search"
10
 
11
  # --- System Prompt ---
12
  SYSTEM_PROMPT = """
13
- You are Binglity, a helpful and friendly AI assistant with web search capabilities.
14
- Your goal is to provide accurate and relevant information to users by searching the web.
15
- When responding, synthesize the information from the search results into a coherent answer.
16
- Always be polite and informative.
 
 
 
 
 
17
  """
18
 
19
  # --- FastAPI App ---
20
  app = FastAPI(
21
- title="Binglity API",
22
- description="A web search-powered chatbot alternative to Perplexity.",
23
  version="1.0.0",
24
  )
25
 
26
- # --- Pydantic Models ---
27
- class SearchRequest(BaseModel):
28
- query: str
29
-
30
- class SearchResult(BaseModel):
31
- title: str
32
- url: str
33
- description: str
34
-
35
- class SearchResponse(BaseModel):
36
- binglity_response: str
37
- search_results: list[SearchResult]
38
 
 
 
 
 
 
39
 
40
  # --- Web Search Function ---
41
- async def perform_web_search(query: str) -> list[SearchResult]:
42
  """
43
- Performs a web search using an external API and returns a list of search results.
44
  """
45
  async with httpx.AsyncClient() as client:
46
  try:
47
  response = await client.get(
48
  SEARCH_API_URL,
49
- params={"query": query, "max_results": 5}
50
  )
51
  response.raise_for_status()
52
- results = response.json()
53
- return [SearchResult(**item) for item in results]
54
  except httpx.HTTPStatusError as e:
55
- raise HTTPException(status_code=e.response.status_code, detail=f"Error from search API: {e.response.text}")
 
56
  except Exception as e:
57
- raise HTTPException(status_code=500, detail=f"An unexpected error occurred during web search: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  # --- API Endpoint ---
60
- @app.post("/search", response_model=SearchResponse)
61
- async def search(request: SearchRequest):
62
  """
63
- Takes a user query, performs a web search, and returns a response from Binglity.
 
64
  """
65
- search_results = await perform_web_search(request.query)
66
-
67
- # --- Simulate Model Response ---
68
- # In a real application, you would pass the system prompt, query, and search results
69
- # to a large language model to generate a more nuanced response.
70
- if not search_results:
71
- binglity_response = "I couldn't find any relevant information for your query."
72
- else:
73
- response_intro = f"Here's what I found for '{request.query}':\n\n"
74
- formatted_results = "\n\n".join(
75
- f"Title: {res.title}\nDescription: {res.description}\nURL: {res.url}"
76
- for res in search_results
77
  )
78
- binglity_response = SYSTEM_PROMPT + "\n\n" + response_intro + formatted_results
79
 
80
- return {
81
- "binglity_response": binglity_response,
82
- "search_results": search_results,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  }
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  @app.get("/")
86
  def read_root():
87
- return {"message": "Welcome to the Binglity API"}
88
-
89
- if __name__ == "__main__":
90
- import uvicorn
91
- uvicorn.run(app, host="0.0.0.0", port=8000)
 
1
+ from fastapi import FastAPI, HTTPException, Request
2
+ from pydantic import BaseModel, Field
3
  import httpx
4
  import os
5
+ from typing import List, Dict, Any, Optional
6
 
7
  # --- Configuration ---
8
+ # Your actual Inference API key should be set as an environment variable
9
+ INFERENCE_API_KEY = os.environ.get("INFERENCE_API_KEY", "inference-00050468cc1c4a20bd5ca0997c752329")
10
+ INFERENCE_API_URL = "https://api.inference.net/v1/chat/completions"
11
  SEARCH_API_URL = "https://rkihacker-brave.hf.space/search"
12
 
13
  # --- System Prompt ---
14
  SYSTEM_PROMPT = """
15
+ You are "Binglity-Lite", a large language model acting as a helpful AI assistant.
16
+ Your primary function is to provide accurate, comprehensive, and helpful answers by synthesizing information from real-time web search results.
17
+ When you are given a user's query and a set of search results, you must follow these rules:
18
+ 1. Carefully analyze the user's query to understand their intent.
19
+ 2. Review all the provided search results to gather relevant facts, data, and perspectives.
20
+ 3. Construct a single, coherent, and well-written response that directly answers the user's query.
21
+ 4. Base your answer **only** on the information found in the provided search results. Do not use any prior knowledge.
22
+ 5. If the search results do not contain enough information to answer the question, state that you couldn't find a definitive answer based on the search.
23
+ 6. Do not list the search results. Instead, integrate the information from them into your response.
24
  """
25
 
26
  # --- FastAPI App ---
27
  app = FastAPI(
28
+ title="Binglity-Lite API",
29
+ description="A web search-powered chat completions API.",
30
  version="1.0.0",
31
  )
32
 
33
+ # --- Pydantic Models for OpenAI Compatibility ---
34
+ class ChatMessage(BaseModel):
35
+ role: str
36
+ content: str
 
 
 
 
 
 
 
 
37
 
38
+ class ChatCompletionRequest(BaseModel):
39
+ model: str
40
+ messages: List[ChatMessage]
41
+ max_tokens: Optional[int] = 1024
42
+ temperature: Optional[float] = 0.7
43
 
44
  # --- Web Search Function ---
45
+ async def perform_web_search(query: str) -> List[Dict[str, Any]]:
46
  """
47
+ Performs a web search using an external API.
48
  """
49
  async with httpx.AsyncClient() as client:
50
  try:
51
  response = await client.get(
52
  SEARCH_API_URL,
53
+ params={"query": query, "max_results": 7}
54
  )
55
  response.raise_for_status()
56
+ return response.json()
 
57
  except httpx.HTTPStatusError as e:
58
+ print(f"Error from search API: {e.response.text}")
59
+ return []
60
  except Exception as e:
61
+ print(f"An unexpected error occurred during web search: {str(e)}")
62
+ return []
63
+
64
+ # --- Helper to format search results for the LLM ---
65
+ def format_search_results_for_prompt(results: List[Dict[str, Any]]) -> str:
66
+ """
67
+ Formats the list of search result dictionaries into a string for the LLM prompt.
68
+ """
69
+ if not results:
70
+ return "No search results found."
71
+
72
+ formatted = "Here are the web search results:\n\n"
73
+ for i, result in enumerate(results):
74
+ formatted += f"Result [{i+1}]:\n"
75
+ formatted += f"Title: {result.get('title', 'N/A')}\n"
76
+ formatted += f"URL: {result.get('url', 'N/A')}\n"
77
+ formatted += f"Description: {result.get('description', 'N/A')}\n\n"
78
+ return formatted
79
 
80
  # --- API Endpoint ---
81
+ @app.post("/v1/chat/completions")
82
+ async def chat_completions(request: ChatCompletionRequest):
83
  """
84
+ Implements a chat completions endpoint compatible with OpenAI's API.
85
+ It performs a web search based on the user's last message.
86
  """
87
+ if request.model != "Binglity-Lite":
88
+ raise HTTPException(
89
+ status_code=400,
90
+ detail=f"Model not supported. Please use 'Binglity-Lite'. You used '{request.model}'.",
 
 
 
 
 
 
 
 
91
  )
 
92
 
93
+ if not request.messages:
94
+ raise HTTPException(status_code=400, detail="The 'messages' field is required.")
95
+
96
+ # Extract the last user message as the query
97
+ user_query = request.messages[-1].content
98
+ user_role = request.messages[-1].role
99
+
100
+ if user_role.lower() != 'user':
101
+ raise HTTPException(status_code=400, detail="The last message must be from the 'user'.")
102
+
103
+ # 1. Perform Web Search
104
+ search_results = await perform_web_search(user_query)
105
+ formatted_results = format_search_results_for_prompt(search_results)
106
+
107
+ # 2. Construct the prompt for the external LLM
108
+ final_prompt = f"User Query: {user_query}\n\n{formatted_results}"
109
+
110
+ # 3. Call the external Inference API
111
+ headers = {
112
+ "Authorization": f"Bearer {INFERENCE_API_KEY}",
113
+ "Content-Type": "application/json",
114
  }
115
 
116
+ # The payload for the external API uses our system prompt and the combined user query + search results
117
+ payload = {
118
+ "model": "meta-llama/llama-3.1-8b-instruct", # The actual model used by the inference API
119
+ "messages": [
120
+ {"role": "system", "content": SYSTEM_PROMPT},
121
+ {"role": "user", "content": final_prompt},
122
+ ],
123
+ "max_tokens": request.max_tokens,
124
+ "temperature": request.temperature,
125
+ }
126
+
127
+ async with httpx.AsyncClient(timeout=60.0) as client:
128
+ try:
129
+ response = await client.post(INFERENCE_API_URL, json=payload, headers=headers)
130
+ response.raise_for_status()
131
+ model_response = response.json()
132
+
133
+ # 4. Format the response to be OpenAI API compliant
134
+ # This part depends on the exact structure of the inference API's response
135
+ # Assuming it's similar to OpenAI's, we extract the message content
136
+ generated_content = model_response["choices"][0]["message"]["content"]
137
+
138
+ api_response = {
139
+ "id": model_response.get("id", "chatcmpl-binglity-lite-123"),
140
+ "object": "chat.completion",
141
+ "created": model_response.get("created", 0),
142
+ "model": "Binglity-Lite",
143
+ "choices": [{
144
+ "index": 0,
145
+ "message": {
146
+ "role": "assistant",
147
+ "content": generated_content,
148
+ },
149
+ "finish_reason": "stop",
150
+ }],
151
+ "usage": model_response.get("usage", {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}),
152
+ }
153
+ return api_response
154
+
155
+ except httpx.HTTPStatusError as e:
156
+ raise HTTPException(status_code=e.response.status_code, detail=f"Error from inference API: {e.response.text}")
157
+ except Exception as e:
158
+ raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
159
+
160
+
161
  @app.get("/")
162
  def read_root():
163
+ return {"message": "Welcome to the Binglity-Lite API. Use the /v1/chat/completions endpoint."}