NujacsaintS commited on
Commit
ff45346
·
verified ·
1 Parent(s): 72cff7b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -58
app.py CHANGED
@@ -5,6 +5,8 @@ from typing import Dict
5
  import time
6
  import os
7
  import httpx
 
 
8
 
9
  app = FastAPI(title="Tessai LLM Bridge", version="0.1.0")
10
 
@@ -95,76 +97,61 @@ def count_active_sessions(window_seconds: int = 300) -> int:
95
 
96
 
97
  # -----------------------------
98
- # LLM integration
99
  # -----------------------------
100
- # Configure via environment variables in Hugging Face:
101
- # TESSAI_LLM_URL = full URL of the model endpoint
102
- # TESSAI_LLM_KEY = auth token (if needed)
103
 
 
104
 
105
- LLM_URL = os.getenv("TESSAI_LLM_URL", "").strip()
106
- LLM_KEY = os.getenv("TESSAI_LLM_KEY", "").strip()
 
 
107
 
108
-
109
- from httpx import HTTPStatusError
110
-
111
- async def call_llm(message: str, context: Dict[str, str] | None = None) -> tuple[str, int]:
112
- if not LLM_URL:
113
- reply = f"[stub] Echo: {message}"
114
- tokens_used = len(message)
115
- return reply, tokens_used
116
-
117
- prompt = message
118
  if context:
119
  ctx_str = "; ".join(f"{k}={v}" for k, v in context.items())
120
- prompt = f"[context: {ctx_str}]\n\n{message}"
121
-
122
- headers = {}
123
- if LLM_KEY:
124
- headers["Authorization"] = f"Bearer {LLM_KEY}"
125
-
126
- payload = {
127
- "inputs": prompt,
128
- "parameters": {
129
- "max_new_tokens": 256,
130
- "temperature": 0.3,
131
- "do_sample": False,
132
- },
133
- }
134
 
135
- try:
136
- async with httpx.AsyncClient(timeout=60.0) as client:
137
- resp = await client.post(LLM_URL, headers=headers, json=payload)
138
- resp.raise_for_status()
139
- data = resp.json()
140
- except HTTPStatusError as e:
141
- # Surface *what HF said* back to the front end instead of 500
142
- body_text = ""
143
- try:
144
- body_text = e.response.text
145
- except Exception:
146
- pass
147
-
148
- reply = (
149
- f"[bridge error] HF returned {e.response.status_code} for {LLM_URL}. "
150
- f"Response body: {body_text}"
151
- )
152
- return reply, 0
153
- except Exception as e:
154
- reply = f"[bridge error] Unexpected exception calling HF: {e}"
155
- return reply, 0
156
 
157
- # Normal happy path
158
- if isinstance(data, list) and data and "generated_text" in data[0]:
159
- full_text = data[0]["generated_text"]
160
- reply = full_text[len(prompt):].strip() or full_text.strip()
161
- else:
162
- reply = str(data)
163
 
164
- tokens_used = len(reply.split())
165
  return reply, tokens_used
166
 
167
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
  # -----------------------------
170
  # API endpoints
 
5
  import time
6
  import os
7
  import httpx
8
+ from transformers import AutoModelForCausalLM, AutoTokenizer
9
+ import torch
10
 
11
  app = FastAPI(title="Tessai LLM Bridge", version="0.1.0")
12
 
 
97
 
98
 
99
  # -----------------------------
100
+ # LLM integration (local model)
101
  # -----------------------------
102
+ # This uses a small local model so we don't depend on HF router / inference URLs.
103
+ # You can later swap "gpt2" for your own model or your notebook code.
 
104
 
105
+ MODEL_NAME = os.getenv("TESSAI_LOCAL_MODEL", "gpt2")
106
 
107
+ print(f"Loading local model: {MODEL_NAME}")
108
+ _tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
109
+ _model = AutoModelForCausalLM.from_pretrained(MODEL_NAME)
110
+ _model.eval() # inference mode
111
 
112
+ @torch.inference_mode()
113
+ def generate_local_reply(message: str, context: Dict[str, str] | None = None) -> tuple[str, int]:
114
+ # Simple prompt format; you can replace with your notebook's prompt engineering
 
 
 
 
 
 
 
115
  if context:
116
  ctx_str = "; ".join(f"{k}={v}" for k, v in context.items())
117
+ prompt = f"[context: {ctx_str}]\n\nUser: {message}\nAssistant:"
118
+ else:
119
+ prompt = f"User: {message}\nAssistant:"
120
+
121
+ inputs = _tokenizer(prompt, return_tensors="pt")
122
+ outputs = _model.generate(
123
+ **inputs,
124
+ max_new_tokens=128,
125
+ do_sample=True,
126
+ temperature=0.7,
127
+ top_p=0.9,
128
+ pad_token_id=_tokenizer.eos_token_id,
129
+ )
 
130
 
131
+ full_text = _tokenizer.decode(outputs[0], skip_special_tokens=True)
132
+ # Heuristic: the reply is whatever came after the prompt
133
+ reply = full_text[len(prompt):].strip() or full_text.strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ # Approx tokens used in the reply
136
+ reply_tokens = _tokenizer.encode(reply)
137
+ tokens_used = len(reply_tokens)
 
 
 
138
 
 
139
  return reply, tokens_used
140
 
141
 
142
+ async def call_llm(message: str, context: Dict[str, str] | None = None) -> tuple[str, int]:
143
+ """
144
+ Main hook used by /v1/chat. Currently calls the local model.
145
+ Later you can swap this to call your custom notebook LLM or an external API.
146
+ """
147
+ try:
148
+ return generate_local_reply(message, context)
149
+ except Exception as e:
150
+ # Last resort: don't crash the bridge, just report an error message
151
+ err = f"[local-llm error] {type(e).__name__}: {e}"
152
+ print(err)
153
+ return err, 0
154
+
155
 
156
  # -----------------------------
157
  # API endpoints