from fastapi import FastAPI
from fastapi.responses import Response
from PIL import Image
import requests
import io
from ultralytics import YOLO
from g4f.client import Client
import edge_tts

app = FastAPI()
model = YOLO('yolov8n.pt')
client = Client()

messages = [{"role": "system", "content": "你是一个人类助手，并且假设你拥有视力，可以看到东西。你的任务是根据user提供的你所看到的内容，回答user的问题。请在接下来的对话中隐藏你是计算机程序这件事，并且模仿的像一个具有视力的人类助手。不要提及你是一个语言模型，不要说提及你无法看到任何东西。"}]

@app.get("/")
async def mainapp(question):
    #   GET IMAGE
    img_raw = requests.get("http://192.168.199.143:8080/photoaf.jpg").content
    img = Image.open(io.BytesIO(img_raw))
    #   RECOGNITION
    results = model.predict(source=img, stream=True)
    for result in results:
        detections = []
        for box in result.boxes:
            class_id = result.names[box.cls[0].item()]
            cords = box.xyxy[0].tolist()
            cords = [round(x) for x in cords]
            confi = round(box.conf[0].item(), 2)
            print("Object type:", class_id)
            print("Coordinates:", cords)
            print("Probability:", confi)
            print("---")
            detections.append({"name" : class_id, "cords" : cords, "conf" : confi})
    #   GET QUESTION
    if detections:
        lst = []
        for i in detections:
            lst.append(i["name"])
        obj = "，".join(lst)
    else:
        obj = "什么都没有"
    content = "假如你看到了你的面前有以下这些东西：" + obj + "。请用中文，以人类助手的身份回答这个问题：" + question
    #   GPT
    messages.append({"role": "user", "content": content})
    response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=messages,
    # proxy="socks5://127.0.0.1:1080"
    )
    messages.append({"role": response.choices[0].message.role, "content": response.choices[0].message.content})
    gpt_reply = messages[-1]["content"]
    print(f"GPT 回答：{gpt_reply}")
    #   TTS
    voices = await edge_tts.VoicesManager.create()
    voices = voices.find(ShortName="zh-CN-XiaoyiNeural")
    communicate = edge_tts.Communicate(gpt_reply, voices[0]["Name"])
    out = bytes()
    async for chunk in communicate.stream():
        if chunk["type"] == "audio":
            out += chunk["data"]
        elif chunk["type"] == "WordBoundary":
            pass
    
    return Response(out, media_type="audio/mpeg")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8080)
