wanazesi commited on
Commit
bf7211c
·
verified ·
1 Parent(s): e196795

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +77 -75
main.py CHANGED
@@ -1,14 +1,14 @@
1
  import os
2
  import json
3
- import time
4
  import httpx
 
5
  from fastapi import FastAPI, Request
6
- from fastapi.responses import JSONResponse
7
  from fastapi.middleware.cors import CORSMiddleware
8
 
9
  app = FastAPI()
10
 
11
- # 允许跨域请求
12
  app.add_middleware(
13
  CORSMiddleware,
14
  allow_origins=["*"],
@@ -16,7 +16,6 @@ app.add_middleware(
16
  allow_headers=["*"],
17
  )
18
 
19
- # 从环境变量获取你的配置
20
  AIROPS_API_KEY = os.environ.get("AIROPS_API_KEY", "")
21
  AIROPS_APP_ID = os.environ.get("AIROPS_APP_ID", "")
22
  INPUT_VAR = os.environ.get("INPUT_VAR_NAME", "input")
@@ -24,79 +23,82 @@ INPUT_VAR = os.environ.get("INPUT_VAR_NAME", "input")
24
  @app.post("/v1/chat/completions")
25
  async def chat_completions(request: Request):
26
  try:
27
- body = await request.json()
28
- except:
29
- body = {}
30
-
31
- messages = body.get("messages", [])
32
-
33
- # 【酒馆特供版】将所有历史消息和设定拼接成一个长剧本
34
- full_context = ""
35
- for msg in messages:
36
- role = msg.get("role", "user").upper()
37
- content = msg.get("content", "")
38
 
39
- # 统一格式化标签,让 AI 知道是谁在说话
40
- if role == "SYSTEM":
41
- full_context += f"[系统设定及角色卡]:\n{content}\n\n"
42
- elif role == "ASSISTANT":
43
- full_context += f"[角色回复]:\n{content}\n\n"
44
- else:
45
- full_context += f"[我的输入]:\n{content}\n\n"
46
 
47
- # 如果没有收到任何消息,给个默认值
48
- if not full_context.strip():
49
- full_context = "[我的输入]:\n你好"
50
-
51
- headers = {
52
- "Authorization": f"Bearer {AIROPS_API_KEY}",
53
- "Content-Type": "application/json"
54
- }
55
-
56
- # 构造 AirOps 需要的数据格式
57
- payload = {
58
- "inputs": {
59
- INPUT_VAR: full_context.strip()
60
  }
61
- }
62
-
63
- # 设置 120 秒超时,防止长文本生成失败
64
- async with httpx.AsyncClient(timeout=120.0) as client:
65
- url = f"https://app.airops.com/public_api/airops_apps/{AIROPS_APP_ID}/execute"
66
 
67
- try:
68
- response = await client.post(url, headers=headers, json=payload)
69
- if response.status_code == 200:
70
- data = response.json()
71
- # 提取 AirOps 返回的文本结果
72
- result_text = data.get("result", "")
73
-
74
- if isinstance(result_text, (dict, list)):
75
- result_text = json.dumps(result_text, ensure_ascii=False)
 
76
 
77
- # 核心修改:取消流式,直接返回标准的 OpenAI 格式 JSON 响应
78
- return {
79
- "id": f"chatcmpl-airops-{int(time.time())}",
80
- "object": "chat.completion",
81
- "created": int(time.time()),
82
- "model": "airops-model",
83
- "choices": [
84
- {
85
- "index": 0,
86
- "message": {
87
- "role": "assistant",
88
- "content": result_text
89
- },
90
- "finish_reason": "stop"
91
- }
92
- ],
93
- "usage": {
94
- "prompt_tokens": 0,
95
- "completion_tokens": 0,
96
- "total_tokens": 0
97
- }
98
- }
99
- else:
100
- return JSONResponse(status_code=500, content={"error": f"AirOps 接口报错: {response.text}"})
101
- except Exception as e:
102
- return JSONResponse(status_code=500, content={"error": f"代理服务器内部错误: {str(e)}"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import json
3
+ import asyncio
4
  import httpx
5
+ import traceback
6
  from fastapi import FastAPI, Request
7
+ from fastapi.responses import StreamingResponse, JSONResponse
8
  from fastapi.middleware.cors import CORSMiddleware
9
 
10
  app = FastAPI()
11
 
 
12
  app.add_middleware(
13
  CORSMiddleware,
14
  allow_origins=["*"],
 
16
  allow_headers=["*"],
17
  )
18
 
 
19
  AIROPS_API_KEY = os.environ.get("AIROPS_API_KEY", "")
20
  AIROPS_APP_ID = os.environ.get("AIROPS_APP_ID", "")
21
  INPUT_VAR = os.environ.get("INPUT_VAR_NAME", "input")
 
23
  @app.post("/v1/chat/completions")
24
  async def chat_completions(request: Request):
25
  try:
26
+ try:
27
+ body = await request.json()
28
+ except:
29
+ body = {}
30
+
31
+ messages = body.get("messages", [])
 
 
 
 
 
32
 
33
+ # 将所有历史消息和设定拼接成一个长剧本
34
+ full_context = ""
35
+ for msg in messages:
36
+ # 强制转换为字符串,防止特殊格式报错
37
+ role = str(msg.get("role", "user")).upper()
38
+ content = str(msg.get("content", ""))
 
39
 
40
+ if role == "SYSTEM":
41
+ full_context += f"[系统设定及角色卡]:\n{content}\n\n"
42
+ elif role == "ASSISTANT":
43
+ full_context += f"[角色回复]:\n{content}\n\n"
44
+ else:
45
+ full_context += f"[我的输入]:\n{content}\n\n"
46
+
47
+ if not full_context.strip():
48
+ full_context = "[我的输入]:\n你好"
49
+
50
+ headers = {
51
+ "Authorization": f"Bearer {AIROPS_API_KEY}",
52
+ "Content-Type": "application/json"
53
  }
 
 
 
 
 
54
 
55
+ payload = {
56
+ "inputs": {
57
+ INPUT_VAR: full_context.strip()
58
+ }
59
+ }
60
+
61
+ async def generate():
62
+ # 同样保持 300 秒超时,给 AI 充分的思考时间
63
+ async with httpx.AsyncClient(timeout=300.0) as client:
64
+ url = f"https://app.airops.com/public_api/airops_apps/{AIROPS_APP_ID}/execute"
65
 
66
+ try:
67
+ response = await client.post(url, headers=headers, json=payload)
68
+
69
+ if response.status_code == 200:
70
+ data = response.json()
71
+ result_text = data.get("result", "")
72
+
73
+ if isinstance(result_text, (dict, list)):
74
+ result_text = json.dumps(result_text, ensure_ascii=False)
75
+
76
+ # 模拟 OpenAI 流式打字机效果
77
+ chunk_size = 3
78
+ for i in range(0, len(result_text), chunk_size):
79
+ chunk = result_text[i:i+chunk_size]
80
+ openai_chunk = {
81
+ "id": "chatcmpl-airops",
82
+ "object": "chat.completion.chunk",
83
+ "choices": [{"delta": {"content": chunk}}]
84
+ }
85
+ yield f"data: {json.dumps(openai_chunk)}\n\n"
86
+ await asyncio.sleep(0.01)
87
+
88
+ yield "data: [DONE]\n\n"
89
+ else:
90
+ print(f"AirOps Error: {response.status_code} - {response.text}")
91
+ err = {"error": f"AirOps 接口报错: {response.status_code}"}
92
+ yield f"data: {json.dumps(err)}\n\n"
93
+ yield "data: [DONE]\n\n"
94
+ except Exception as e:
95
+ traceback.print_exc()
96
+ err = {"error": f"代理服务器内部错误: {repr(e)}"}
97
+ yield f"data: {json.dumps(err)}\n\n"
98
+ yield "data: [DONE]\n\n"
99
+
100
+ return StreamingResponse(generate(), media_type="text/event-stream")
101
+
102
+ except Exception as e:
103
+ traceback.print_exc()
104
+ return JSONResponse(status_code=500, content={"error": f"请求解析错误: {repr(e)}"})