Wilker commited on
Commit
01dc751
Β·
1 Parent(s): c58fbd9

fix(app): reordena schemas de tools/Anthropic e adiciona from __future__ import annotations

Browse files
Files changed (1) hide show
  1. app.py +56 -37
app.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  from fastapi import FastAPI, HTTPException, Form, File, UploadFile, Request, Depends
2
  from fastapi.responses import HTMLResponse, FileResponse, PlainTextResponse, RedirectResponse, StreamingResponse, JSONResponse
3
  from starlette.middleware.sessions import SessionMiddleware
@@ -411,6 +413,41 @@ logger.info("Construindo Γ­ndices de conhecimento (RAG) e skills...")
411
  reload_indexes()
412
 
413
  # ── Schemas ────────────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  class Message(BaseModel):
415
  role: Literal["system", "user", "assistant"]
416
  content: constr(min_length=1, max_length=10000)
@@ -430,6 +467,8 @@ class ChatRequest(BaseModel):
430
  messages: List[Message] = Field(min_length=1, description="Lista de mensagens")
431
  max_tokens: Optional[int] = Field(default=8192, ge=1, le=1000000, description="MΓ‘ximo de tokens")
432
  temperature: Optional[float] = Field(default=0.7, ge=0.0, le=2.0, description="Temperatura de geraΓ§Γ£o")
 
 
433
 
434
  @field_validator("model")
435
  @classmethod
@@ -448,6 +487,23 @@ class ChatRequest(BaseModel):
448
  raise ValueError("messages nΓ£o pode estar vazio")
449
  return v
450
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
  class ImageRequest(BaseModel):
452
  prompt: constr(min_length=1, max_length=1000) = Field(description="Prompt para geraΓ§Γ£o de imagem")
453
  negative_prompt: Optional[constr(max_length=500)] = Field(default=None, description="Prompt negativo")
@@ -1271,43 +1327,6 @@ def list_transcription_models():
1271
  ]
1272
  }
1273
 
1274
- # ── Endpoint β€” Anthropic-compatible /v1/messages ──────────────────────────────
1275
- class AnthropicMessage(BaseModel):
1276
- role: str
1277
- content: str
1278
-
1279
-
1280
- class AnthropicTool(BaseModel):
1281
- name: str
1282
- description: Optional[str] = None
1283
- input_schema: Optional[dict] = Field(default=None, alias="input_schema")
1284
-
1285
- @field_validator("input_schema", mode="before")
1286
- @classmethod
1287
- def coerce_input_schema(cls, v):
1288
- if v is None:
1289
- return {"type": "object", "properties": {}}
1290
- return v
1291
-
1292
-
1293
- class AnthropicRequest(BaseModel):
1294
- model: Optional[str] = Field(default=DEFAULT_MODEL_KEY)
1295
- messages: List[AnthropicMessage]
1296
- max_tokens: Optional[int] = Field(default=8192)
1297
- temperature: Optional[float] = Field(default=0.7)
1298
- system: Optional[str] = None
1299
- stream: Optional[bool] = False
1300
- tools: Optional[List[AnthropicTool]] = Field(default=None, description="Ferramentas no formato Anthropic")
1301
- tool_choice: Optional[str] = Field(default="auto", description="'auto', 'any', ou nome de uma tool")
1302
-
1303
- @field_validator("messages")
1304
- @classmethod
1305
- def messages_not_empty(cls, v):
1306
- if not v:
1307
- raise ValueError("messages nΓ£o pode estar vazio")
1308
- return v
1309
-
1310
-
1311
  async def chat_completions_async(req: ChatRequest):
1312
  """VersΓ£o async do chat_completions β€” usada pelos endpoints SSE."""
1313
  try:
 
1
+ from __future__ import annotations
2
+
3
  from fastapi import FastAPI, HTTPException, Form, File, UploadFile, Request, Depends
4
  from fastapi.responses import HTMLResponse, FileResponse, PlainTextResponse, RedirectResponse, StreamingResponse, JSONResponse
5
  from starlette.middleware.sessions import SessionMiddleware
 
413
  reload_indexes()
414
 
415
  # ── Schemas ────────────────────────────────────────────────────────────────────
416
+ class ToolFunctionParameters(BaseModel):
417
+ type: str = "object"
418
+ properties: dict = {}
419
+ required: Optional[List[str]] = None
420
+
421
+
422
+ class ToolFunction(BaseModel):
423
+ name: str
424
+ description: Optional[str] = None
425
+ parameters: Optional[ToolFunctionParameters] = None
426
+
427
+
428
+ class Tool(BaseModel):
429
+ type: Literal["function"] = "function"
430
+ function: ToolFunction
431
+
432
+
433
+ class AnthropicMessage(BaseModel):
434
+ role: str
435
+ content: str
436
+
437
+
438
+ class AnthropicTool(BaseModel):
439
+ name: str
440
+ description: Optional[str] = None
441
+ input_schema: Optional[dict] = Field(default=None, alias="input_schema")
442
+
443
+ @field_validator("input_schema", mode="before")
444
+ @classmethod
445
+ def coerce_input_schema(cls, v):
446
+ if v is None:
447
+ return {"type": "object", "properties": {}}
448
+ return v
449
+
450
+
451
  class Message(BaseModel):
452
  role: Literal["system", "user", "assistant"]
453
  content: constr(min_length=1, max_length=10000)
 
467
  messages: List[Message] = Field(min_length=1, description="Lista de mensagens")
468
  max_tokens: Optional[int] = Field(default=8192, ge=1, le=1000000, description="MΓ‘ximo de tokens")
469
  temperature: Optional[float] = Field(default=0.7, ge=0.0, le=2.0, description="Temperatura de geraΓ§Γ£o")
470
+ tools: Optional[List[Tool]] = Field(default=None, description="Ferramentas disponΓ­veis (formato OpenAI)")
471
+ tool_choice: Optional[str] = Field(default="auto", description="'auto', 'none', ou nome de uma tool")
472
 
473
  @field_validator("model")
474
  @classmethod
 
487
  raise ValueError("messages nΓ£o pode estar vazio")
488
  return v
489
 
490
+ class AnthropicRequest(BaseModel):
491
+ model: Optional[str] = Field(default=DEFAULT_MODEL_KEY)
492
+ messages: List[AnthropicMessage]
493
+ max_tokens: Optional[int] = Field(default=8192)
494
+ temperature: Optional[float] = Field(default=0.7)
495
+ system: Optional[str] = None
496
+ stream: Optional[bool] = False
497
+ tools: Optional[List[AnthropicTool]] = Field(default=None, description="Ferramentas no formato Anthropic")
498
+ tool_choice: Optional[str] = Field(default="auto", description="'auto', 'any', ou nome de uma tool")
499
+
500
+ @field_validator("messages")
501
+ @classmethod
502
+ def messages_not_empty(cls, v):
503
+ if not v:
504
+ raise ValueError("messages nΓ£o pode estar vazio")
505
+ return v
506
+
507
  class ImageRequest(BaseModel):
508
  prompt: constr(min_length=1, max_length=1000) = Field(description="Prompt para geraΓ§Γ£o de imagem")
509
  negative_prompt: Optional[constr(max_length=500)] = Field(default=None, description="Prompt negativo")
 
1327
  ]
1328
  }
1329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1330
  async def chat_completions_async(req: ChatRequest):
1331
  """VersΓ£o async do chat_completions β€” usada pelos endpoints SSE."""
1332
  try: