1
+ import os
2
+ import time
3
+ import asyncio
4
+ from fastapi import FastAPI , File , UploadFile , HTTPException , status
5
+ from fastapi .middleware .cors import CORSMiddleware
6
+ from fastapi .responses import FileResponse
7
+ import aiofiles
8
+ from markitdown import MarkItDown
9
+ from starlette .responses import JSONResponse
10
+ from urllib .parse import unquote
11
+ from openai import OpenAI
12
+ from contextlib import asynccontextmanager
13
+ from pathlib import Path
14
+ from typing import Dict
15
+
16
+ @asynccontextmanager
17
+ async def lifespan (app : FastAPI ):
18
+ # 启动时执行
19
+ banner_path = Path (__file__ ).parent / 'banner.txt'
20
+ try :
21
+ with open (banner_path , 'r' , encoding = 'utf-8' ) as f :
22
+ banner = f .read ()
23
+ print (banner )
24
+ except FileNotFoundError :
25
+ print ("Banner file not found, starting server without banner..." )
26
+ yield
27
+ app = FastAPI (lifespan = lifespan )
28
+
29
+ client = OpenAI (
30
+ base_url = "https://open.bigmodel.cn/api/paas/v4" ,
31
+ api_key = "9dfee4d072cf964f117403933da51242.1s1Tvn56OIGQkvmT"
32
+ )
33
+
34
+ # Add CORS middleware
35
+ app .add_middleware (
36
+ CORSMiddleware ,
37
+ allow_origins = ["*" ], # Allows all origins
38
+ allow_credentials = True ,
39
+ allow_methods = ["*" ], # Allows all methods
40
+ allow_headers = ["*" ], # Allows all headers
41
+ )
42
+
43
+ async def delete_files (file_path : str , output_path : str , delay : int ):
44
+ await asyncio .sleep (delay )
45
+ if os .path .exists (file_path ):
46
+ os .remove (file_path )
47
+ if os .path .exists (output_path ):
48
+ os .remove (output_path )
49
+
50
+ @app .post ("/upload/" ,
51
+ response_model = Dict [str , str ],
52
+ status_code = status .HTTP_200_OK ,
53
+ summary = "上传图片文件" ,
54
+ description = "上传图片文件并提取其中的文本内容" ,
55
+ responses = {
56
+ 200 : {
57
+ "description" : "成功提取文本" ,
58
+ "content" : {
59
+ "application/json" : {
60
+ "example" : {
61
+ "new_filename" : "1679012345.jpg" ,
62
+ "content" : "提取的文本内容"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ )
69
+ async def upload_file (
70
+ file : UploadFile = File (..., description = "要上传的图片文件,支持常见图片格式" )
71
+ ):
72
+ if not os .path .exists ('tmp' ):
73
+ os .makedirs ('tmp' )
74
+
75
+ original_filename = os .path .splitext (file .filename )[0 ]
76
+ timestamp = int (time .time ())
77
+ file_extension = os .path .splitext (file .filename )[1 ]
78
+ new_filename = f"{ timestamp } { file_extension } "
79
+ file_path = f"files/{ new_filename } "
80
+
81
+ async with aiofiles .open (file_path , 'wb' ) as out_file :
82
+ content = await file .read ()
83
+ await out_file .write (content )
84
+
85
+ markitdown = MarkItDown (mlm_client = client , mlm_model = "glm-4v-flash" )
86
+ result = markitdown .convert (file_path , mlm_prompt = "提取图片中全部的文本,不需要任何推理和总结,只需要原文" )
87
+
88
+ # Schedule file deletion after 10 minutes (600 seconds)
89
+ asyncio .create_task (delete_files (file_path , "" , 600 ))
90
+
91
+ return {
92
+ "new_filename" : new_filename ,
93
+ "content" : result .text_content
94
+ }
95
+
96
+ @app .exception_handler (HTTPException )
97
+ async def http_exception_handler (request , exc ):
98
+ return JSONResponse (
99
+ status_code = exc .status_code ,
100
+ content = {"message" : exc .detail },
101
+ )
0 commit comments