File size: 4,405 Bytes
4a37e76 6323db7 4a37e76 6323db7 4a37e76 6323db7 4a37e76 6323db7 4a37e76 e80d8fd 4a37e76 bdcb7a6 4a37e76 bdcb7a6 e80d8fd 4a37e76 e80d8fd 4a37e76 e80d8fd 4a37e76 e80d8fd 4a37e76 6323db7 4a37e76 6323db7 4a37e76 e80d8fd 6323db7 e80d8fd 6323db7 e80d8fd 6323db7 4a37e76 6323db7 e80d8fd 6323db7 4a37e76 6323db7 ac07a29 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | import json
import os
import uuid
from pathlib import Path
from flask import Flask, render_template, request, jsonify, send_from_directory
from openai import OpenAI
from faster_whisper import WhisperModel
from pipeline import run_pipeline
app = Flask(__name__, static_folder='static', template_folder='templates')
UPLOAD_FOLDER = Path('uploads')
UPLOAD_FOLDER.mkdir(exist_ok=True)
AMD_ENDPOINT = os.environ.get("AMD_ENDPOINT", "http://134.199.198.41:8000/v1")
MODEL_NAME = os.environ.get("MODEL_NAME", "Qwen/Qwen3-14B")
llm_client = OpenAI(base_url=AMD_ENDPOINT, api_key="not-required")
whisper_model = WhisperModel("base", device="cpu", compute_type="int8")
def call_llm(prompt, max_tokens=200):
response = llm_client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
temperature=0.3,
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
content = response.choices[0].message.content.strip()
if "</think>" in content:
content = content.split("</think>")[-1].strip()
if content.startswith("```"):
content = content.split("\n", 1)[1].rsplit("```", 1)[0].strip()
return content
@app.route('/')
def index():
return render_template('index.html')
@app.route('/session')
def session():
return render_template('session.html')
@app.route('/summarize', methods=['POST'])
def summarize():
data = request.get_json()
text = data.get('text', '')
category = data.get('category', 'legal')
if not text.strip():
return jsonify({'summary': '', 'keywords': []})
try:
prompt = f"""You are Ken, an AI co-listener. A user is about to enter a {category} consultation.
Their input: "{text}"
Return JSON with:
1. "summary": A 2-3 sentence summary of their situation (concise, factual)
2. "keywords": An array of 3-5 key topics/concerns to listen for during the conversation
Return ONLY valid JSON, no other text."""
content = call_llm(prompt, max_tokens=200)
result = json.loads(content)
return jsonify(result)
except Exception as e:
print(f"Summarize error: {e}")
return jsonify({'summary': text[:200], 'keywords': []})
@app.route('/transcribe', methods=['POST'])
def transcribe():
if 'audio' not in request.files:
return jsonify({'error': 'No audio'}), 400
audio_file = request.files['audio']
audio_path = UPLOAD_FOLDER / f'{uuid.uuid4().hex}.webm'
audio_file.save(audio_path)
try:
segments, _ = whisper_model.transcribe(str(audio_path), beam_size=3, language="en")
text = " ".join(seg.text.strip() for seg in segments)
audio_path.unlink(missing_ok=True)
return jsonify({'text': text})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/process', methods=['POST'])
def process():
if 'video' not in request.files:
return jsonify({'error': 'No video file'}), 400
video_file = request.files['video']
profile_text = request.form.get('profile_text', '')
profile_cat = request.form.get('profile_cat', 'Legal')
video_path = UPLOAD_FOLDER / f'{uuid.uuid4().hex}_{video_file.filename}'
video_file.save(video_path)
# Summarize via shared LLM helper
summary = ""
if profile_text.strip():
try:
prompt = f"""Summarize this user's situation in 2-3 concise sentences for a {profile_cat} consultation. Focus on key facts and concerns.\n\nUser input: "{profile_text}"\n\nReturn ONLY the summary."""
summary = call_llm(prompt, max_tokens=150)
except Exception as e:
print(f"Summarization error: {e}")
summary = profile_text[:200]
profile = {
"name": "User",
"situation": summary or f"{profile_cat}: {profile_text}",
"knowledge_level": "intermediate",
"concerns": [profile_text] if profile_text else []
}
result = run_pipeline(str(video_path), profile)
result['summary'] = summary
video_path.unlink(missing_ok=True)
return jsonify(result)
@app.route('/uploads/<path:filename>')
def uploaded_file(filename):
return send_from_directory(UPLOAD_FOLDER, filename)
if __name__ == '__main__':
debug = os.environ.get('DEBUG', 'false').lower() == 'true'
app.run(host='0.0.0.0', port=7860, debug=debug)
|