XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/gpt4free

Improve logging

6106ca95
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

5 个文件 +56 -16
Modified docker/Dockerfile-slim +1 -1
@@ -36,4 +36,4 @@ RUN git clone https://github.com/hlohaus/deepseek4free.git \
36 36 && cd deepseek4free && git checkout 21Feb \
37 37 && pip install --no-cache-dir . && cd .. && rm -rf deepseek4free
38 38
39 CMD git pull origin main && docker/update.sh & docker/start.sh
39 CMD python -m etc.tool.update && docker/update.sh & docker/start.sh
Modified docker/update.sh +1 -1
@@ -15,7 +15,7 @@ echo "UPDATE: d$c"
15 15 git pull origin main
16 16 sleep 120
17 17 echo "UPDATE: #$c"
18 python -m etc.tool.update
18 git pull origin main
19 19 sleep 120
20 20 done
21 21 echo "STOPPED."
Modified g4f/api/__init__.py +16 -5
@@ -188,6 +188,13 @@ class AppConfig:
188 188 for key, value in data.items():
189 189 setattr(cls, key, value)
190 190
191 def remove_authorization(request: Request) -> Request:
192 new_header = request.headers.mutablecopy()
193 del new_header["authorization"]
194 request.scope["headers"] = new_header.raw
195 delattr(request, "_headers")
196 return request
197
191 198 class Api:
192 199 def __init__(self, app: FastAPI) -> None:
193 200 self.app = app
@@ -220,14 +227,16 @@ class Api:
220 227 session_key = get_session_key()
221 228 @self.app.middleware("http")
222 229 async def authorization(request: Request, call_next):
230 user = None
223 231 if AppConfig.g4f_api_key is not None or AppConfig.demo:
232 is_authorization_header = False
224 233 try:
225 234 user_g4f_api_key = await self.get_g4f_api_key(request)
226 235 except HTTPException:
227 236 user_g4f_api_key = await self.security(request)
228 237 if hasattr(user_g4f_api_key, "credentials"):
229 238 user_g4f_api_key = user_g4f_api_key.credentials
230 user = None
239 is_authorization_header = True
231 240 if AppConfig.g4f_api_key is None or not secrets.compare_digest(AppConfig.g4f_api_key, user_g4f_api_key):
232 241 if has_crypto and user_g4f_api_key:
233 242 try:
@@ -260,10 +269,12 @@ class Api:
260 269 user = await self.get_username(request)
261 270 except HTTPException as e:
262 271 return ErrorResponse.from_message(e.detail, e.status_code, e.headers)
263 response = await call_next(request)
264 response.headers["x-user"] = user
265 return response
266 return await call_next(request)
272 if is_authorization_header:
273 request = remove_authorization(request)
274 response = await call_next(request)
275 if user is not None:
276 response.headers["x_user"] = user
277 return response
267 278
268 279 def register_validation_exception_handler(self):
269 280 @self.app.exception_handler(RequestValidationError)
Modified g4f/gui/server/backend_api.py +7 -0
@@ -214,6 +214,13 @@ class Backend_Api(Api):
214 214 with cache_file.open("a" if cache_file.exists() else "w") as f:
215 215 f.write(f"{json.dumps(request.json)}\n")
216 216 return {}
217
218 @app.route('/backend-api/v2/usage/<date>', methods=['GET'])
219 def get_usage(date: str):
220 cache_dir = Path(get_cookies_dir()) / ".usage"
221 cache_file = cache_dir / f"{date}.jsonl"
222 print(f"Loading usage data from {cache_file}")
223 return cache_file.read_text() if cache_file.exists() else (jsonify({"error": {"message": "No usage data found for this date"}}), 404)
217 224
218 225 @app.route('/backend-api/v2/log', methods=['POST'])
219 226 def add_log():
Modified g4f/tools/run_tools.py +31 -9
@@ -5,13 +5,14 @@ import re
5 5 import json
6 6 import asyncio
7 7 import time
8 import datetime
8 9 from pathlib import Path
9 from typing import Optional, Callable, AsyncIterator, Iterator, Dict, Any, Tuple, List, Union
10 from typing import Optional, AsyncIterator, Iterator, Dict, Any, Tuple, List, Union
10 11
11 12 from ..typing import Messages
12 13 from ..providers.helper import filter_none
13 14 from ..providers.asyncio import to_async_iterator
14 from ..providers.response import Reasoning, FinishReason, Sources
15 from ..providers.response import Reasoning, FinishReason, Sources, Usage, ProviderInfo
15 16 from ..providers.types import ProviderType
16 17 from ..cookies import get_cookies_dir
17 18 from .web_search import do_search, get_search_message
@@ -141,7 +142,7 @@ class AuthManager:
141 142 env_var = f"{cls.aliases[provider_name].upper()}_API_KEY"
142 143 api_key = os.environ.get(env_var)
143 144 if api_key:
144 debug.log(f"Loading API key from environment variable {env_var}")
145 print(f"Loading API key for {provider_name} from environment variable {env_var}")
145 146 return api_key
146 147 return None
147 148
@@ -236,9 +237,10 @@ async def async_iter_run_tools(
236 237 messages, sources = await perform_web_search(messages, web_search)
237 238
238 239 # Get API key
239 api_key = AuthManager.load_api_key(provider)
240 if api_key:
241 kwargs["api_key"] = api_key
240 if not kwargs.get("api_key"):
241 api_key = AuthManager.load_api_key(provider)
242 if api_key:
243 kwargs["api_key"] = api_key
242 244
243 245 # Process tool calls
244 246 if tool_calls:
@@ -248,9 +250,19 @@ async def async_iter_run_tools(
248 250 # Generate response
249 251 response = to_async_iterator(provider.async_create_function(model=model, messages=messages, **kwargs))
250 252
253 model_info = model
251 254 async for chunk in response:
255 if isinstance(chunk, ProviderInfo):
256 model_info = getattr(chunk, 'model', model_info)
257 elif isinstance(chunk, Usage):
258 usage = {"user": kwargs.get("user"), "model": model_info, "provider": provider.get_parent(), **chunk.get_dict()}
259 usage_dir = Path(get_cookies_dir()) / ".usage"
260 usage_file = usage_dir / f"{datetime.date.today()}.jsonl"
261 usage_dir.mkdir(parents=True, exist_ok=True)
262 with usage_file.open("a" if usage_file.exists() else "w") as f:
263 f.write(f"{json.dumps(usage)}\n")
252 264 yield chunk
253
265
254 266 # Yield sources if available
255 267 if sources:
256 268 yield sources
@@ -277,7 +289,7 @@ def iter_run_tools(
277 289 debug.error(f"Couldn't do web search:", e)
278 290
279 291 # Get API key if needed
280 if provider is not None:
292 if not kwargs.get("api_key"):
281 293 api_key = AuthManager.load_api_key(provider)
282 294 if api_key:
283 295 kwargs["api_key"] = api_key
@@ -321,7 +333,7 @@ def iter_run_tools(
321 333 # Process response chunks
322 334 thinking_start_time = 0
323 335 processor = ThinkingProcessor()
324
336 model_info = model
325 337 for chunk in provider.create_function(model=model, messages=messages, provider=provider, **kwargs):
326 338 if isinstance(chunk, FinishReason):
327 339 if sources is not None:
@@ -331,6 +343,16 @@ def iter_run_tools(
331 343 continue
332 344 elif isinstance(chunk, Sources):
333 345 sources = None
346 elif isinstance(chunk, ProviderInfo):
347 model_info = getattr(chunk, 'model', model_info)
348 elif isinstance(chunk, Usage):
349 usage = {"user": kwargs.get("user"), "model": model_info, "provider": provider.get_parent(), **chunk.get_dict()}
350 usage_dir = Path(get_cookies_dir()) / ".usage"
351 usage_file = usage_dir / f"{datetime.date.today()}.jsonl"
352 usage_dir.mkdir(parents=True, exist_ok=True)
353 with usage_file.open("a" if usage_file.exists() else "w") as f:
354 f.write(f"{json.dumps(usage)}\n")
355
334 356 if not isinstance(chunk, str):
335 357 yield chunk
336 358 continue