Yuruyuruu commited on
Commit
ca27728
·
verified ·
1 Parent(s): 730fbff

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +121 -0
main.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import requests
4
+ from fastapi import FastAPI, HTTPException
5
+ from pydantic import BaseModel
6
+ from typing import List, Optional
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+
9
+ app = FastAPI()
10
+
11
+ # Add CORS for Blazor WASM
12
+ app.add_middleware(
13
+ CORSMiddleware,
14
+ allow_origins=["*"],
15
+ allow_credentials=True,
16
+ allow_methods=["*"],
17
+ allow_headers=["*"],
18
+ )
19
+
20
+ class ChatHistoryItem(BaseModel):
21
+ role: str
22
+ content: str
23
+
24
+ class ChatRequest(BaseModel):
25
+ message: str
26
+ history: List[ChatHistoryItem]
27
+
28
+ class BookEnrichment(BaseModel):
29
+ title: Optional[str] = None
30
+ author: Optional[str] = None
31
+ cover_url: Optional[str] = None
32
+ description: Optional[str] = None
33
+ isbn: Optional[str] = None
34
+
35
+ class ChatResponse(BaseModel):
36
+ response: str
37
+ book_data: Optional[BookEnrichment] = None
38
+
39
+ # HF Inference API Settings
40
+ # You can get a token from https://huggingface.co/settings/tokens
41
+ HF_TOKEN = os.getenv("HF_TOKEN")
42
+ MODEL_ID = "mistralai/Mistral-7B-Instruct-v0.2"
43
+
44
+ def query_llm(prompt: str):
45
+ if not HF_TOKEN:
46
+ return "I'm a local librarian helper. (Note: HF_TOKEN is missing in backend settings)"
47
+
48
+ api_url = f"https://api-inference.huggingface.co/models/{MODEL_ID}"
49
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
50
+
51
+ # Format prompt for Mistral
52
+ # Instruction: ...
53
+ # [INST] user message [/INST]
54
+
55
+ payload = {
56
+ "inputs": f"[INST] You are a professional and friendly librarian at 'LibraryLuxe'. Keep responses concise and helpful. \\n\\n {prompt} [/INST]",
57
+ "parameters": {"max_new_tokens": 250, "temperature": 0.7}
58
+ }
59
+
60
+ try:
61
+ response = requests.post(api_url, headers=headers, json=payload)
62
+ res_json = response.json()
63
+ if isinstance(res_json, list) and len(res_json) > 0:
64
+ full_text = res_json[0].get("generated_text", "")
65
+ # Remove the prompt from the response if the model echoes it
66
+ return full_text.split("[/INST]")[-1].strip()
67
+ return "I encountered an error while thinking. Please try again."
68
+ except Exception as e:
69
+ return f"Error: {str(e)}"
70
+
71
+ def get_book_details(isbn: str) -> Optional[BookEnrichment]:
72
+ try:
73
+ # Open Library API
74
+ url = f"https://openlibrary.org/api/books?bibkeys=ISBN:{isbn}&format=json&jscmd=data"
75
+ response = requests.get(url)
76
+ data = response.json()
77
+
78
+ key = f"ISBN:{isbn}"
79
+ if key in data:
80
+ book_info = data[key]
81
+ return BookEnrichment(
82
+ title=book_info.get("title"),
83
+ author=", ".join([a.get("name") for a in book_info.get("authors", [])]),
84
+ cover_url=book_info.get("cover", {}).get("large"),
85
+ description=book_info.get("notes", "No description available."),
86
+ isbn=isbn
87
+ )
88
+ except:
89
+ pass
90
+ return None
91
+
92
+ @app.post("/chat", response_model=ChatResponse)
93
+ async def chat(request: ChatRequest):
94
+ message = request.message
95
+
96
+ # 1. Detect ISBN
97
+ isbn_match = re.search(r"\b\d{10,13}\b", message)
98
+ book_data = None
99
+
100
+ if isbn_match:
101
+ isbn = isbn_match.group(0)
102
+ book_data = get_book_details(isbn)
103
+ if book_data:
104
+ # If we found a book, prepend some context for the LLM
105
+ message = f"User is asking about a book with ISBN {isbn}. I found: {book_data.title} by {book_data.author}. {message}"
106
+
107
+ # 2. Call LLM
108
+ # In a real app, you'd pass the whole history to the LLM
109
+ history_context = "\\n".join([f"{h.role}: {h.content}" for h in request.history[-4:]])
110
+ prompt = f"History:\\n{history_context}\\n\\nUser: {message}"
111
+
112
+ ai_response = query_llm(prompt)
113
+
114
+ return ChatResponse(
115
+ response=ai_response,
116
+ book_data=book_data
117
+ )
118
+
119
+ if __name__ == "__main__":
120
+ import uvicorn
121
+ uvicorn.run(app, host="0.0.0.0", port=8000)