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

XFEstudio/gpt4free

Add Ollama provider, Add vision support to Openai

8fcf618b
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

8 个文件 +72 -32
Modified g4f/Provider/Bing.py +5 -2
@@ -457,10 +457,13 @@ async def stream_generate(
457 457 returned_text = ''
458 458 message_id = None
459 459 while do_read:
460 msg = await wss.receive_str()
460 try:
461 msg = await wss.receive_str()
462 except TypeError:
463 continue
461 464 objects = msg.split(Defaults.delimiter)
462 465 for obj in objects:
463 if obj is None or not obj:
466 if not obj:
464 467 continue
465 468 try:
466 469 response = json.loads(obj)
Modified g4f/Provider/DeepInfra.py +1 -16
@@ -1,8 +1,7 @@
1 1 from __future__ import annotations
2 2
3 3 import requests
4 from ..typing import AsyncResult, Messages, ImageType
5 from ..image import to_data_uri
4 from ..typing import AsyncResult, Messages
6 5 from .needs_auth.Openai import Openai
7 6
8 7 class DeepInfra(Openai):
@@ -33,7 +32,6 @@ class DeepInfra(Openai):
33 32 model: str,
34 33 messages: Messages,
35 34 stream: bool,
36 image: ImageType = None,
37 35 api_base: str = "https://api.deepinfra.com/v1/openai",
38 36 temperature: float = 0.7,
39 37 max_tokens: int = 1028,
@@ -54,19 +52,6 @@ class DeepInfra(Openai):
54 52 'sec-ch-ua-mobile': '?0',
55 53 'sec-ch-ua-platform': '"macOS"',
56 54 }
57 if image is not None:
58 if not model:
59 model = cls.default_vision_model
60 messages[-1]["content"] = [
61 {
62 "type": "image_url",
63 "image_url": {"url": to_data_uri(image)}
64 },
65 {
66 "type": "text",
67 "text": messages[-1]["content"]
68 }
69 ]
70 55 return super().create_async_generator(
71 56 model, messages,
72 57 stream=stream,
Added g4f/Provider/Ollama.py +33 -0
@@ -0,0 +1,33 @@
1 from __future__ import annotations
2
3 import requests
4
5 from .needs_auth.Openai import Openai
6 from ..typing import AsyncResult, Messages
7
8 class Ollama(Openai):
9 label = "Ollama"
10 url = "https://ollama.com"
11 needs_auth = False
12 working = True
13
14 @classmethod
15 def get_models(cls):
16 if not cls.models:
17 url = 'http://127.0.0.1:11434/api/tags'
18 models = requests.get(url).json()["models"]
19 cls.models = [model['name'] for model in models]
20 cls.default_model = cls.models[0]
21 return cls.models
22
23 @classmethod
24 def create_async_generator(
25 cls,
26 model: str,
27 messages: Messages,
28 api_base: str = "http://localhost:11434/v1",
29 **kwargs
30 ) -> AsyncResult:
31 return super().create_async_generator(
32 model, messages, api_base=api_base, **kwargs
33 )
Modified g4f/Provider/__init__.py +1 -0
@@ -43,6 +43,7 @@ from .Llama import Llama
43 43 from .Local import Local
44 44 from .MetaAI import MetaAI
45 45 from .MetaAIAccount import MetaAIAccount
46 from .Ollama import Ollama
46 47 from .PerplexityLabs import PerplexityLabs
47 48 from .Pi import Pi
48 49 from .Replicate import Replicate
Modified g4f/Provider/needs_auth/Openai.py +17 -4
@@ -4,9 +4,10 @@ import json
4 4
5 5 from ..helper import filter_none
6 6 from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin, FinishReason
7 from ...typing import Union, Optional, AsyncResult, Messages
7 from ...typing import Union, Optional, AsyncResult, Messages, ImageType
8 8 from ...requests import StreamSession, raise_for_status
9 9 from ...errors import MissingAuthError, ResponseError
10 from ...image import to_data_uri
10 11
11 12 class Openai(AsyncGeneratorProvider, ProviderModelMixin):
12 13 label = "OpenAI API"
@@ -23,6 +24,7 @@ class Openai(AsyncGeneratorProvider, ProviderModelMixin):
23 24 messages: Messages,
24 25 proxy: str = None,
25 26 timeout: int = 120,
27 image: ImageType = None,
26 28 api_key: str = None,
27 29 api_base: str = "https://api.openai.com/v1",
28 30 temperature: float = None,
@@ -36,6 +38,19 @@ class Openai(AsyncGeneratorProvider, ProviderModelMixin):
36 38 ) -> AsyncResult:
37 39 if cls.needs_auth and api_key is None:
38 40 raise MissingAuthError('Add a "api_key"')
41 if image is not None:
42 if not model and hasattr(cls, "default_vision_model"):
43 model = cls.default_vision_model
44 messages[-1]["content"] = [
45 {
46 "type": "image_url",
47 "image_url": {"url": to_data_uri(image)}
48 },
49 {
50 "type": "text",
51 "text": messages[-1]["content"]
52 }
53 ]
39 54 async with StreamSession(
40 55 proxies={"all": proxy},
41 56 headers=cls.get_headers(stream, api_key, headers),
@@ -51,7 +66,6 @@ class Openai(AsyncGeneratorProvider, ProviderModelMixin):
51 66 stream=stream,
52 67 **extra_data
53 68 )
54
55 69 async with session.post(f"{api_base.rstrip('/')}/chat/completions", json=data) as response:
56 70 await raise_for_status(response)
57 71 if not stream:
@@ -103,8 +117,7 @@ class Openai(AsyncGeneratorProvider, ProviderModelMixin):
103 117 "Content-Type": "application/json",
104 118 **(
105 119 {"Authorization": f"Bearer {api_key}"}
106 if cls.needs_auth and api_key is not None
107 else {}
120 if api_key is not None else {}
108 121 ),
109 122 **({} if headers is None else headers)
110 123 }
Modified g4f/api/__init__.py +1 -1
@@ -201,7 +201,7 @@ def run_api(
201 201 if bind is not None:
202 202 host, port = bind.split(":")
203 203 uvicorn.run(
204 f"g4f.api:{'create_app_debug' if debug else 'create_app'}",
204 f"g4f.api:create_app{'_debug' if debug else ''}",
205 205 host=host, port=int(port),
206 206 workers=workers,
207 207 use_colors=use_colors,
Modified g4f/cli.py +13 -8
@@ -11,6 +11,10 @@ def main():
11 11 api_parser = subparsers.add_parser("api")
12 12 api_parser.add_argument("--bind", default="0.0.0.0:1337", help="The bind string.")
13 13 api_parser.add_argument("--debug", action="store_true", help="Enable verbose logging.")
14 api_parser.add_argument("--model", default=None, help="Default model for chat completion. (incompatible with --debug and --workers)")
15 api_parser.add_argument("--provider", choices=[provider.__name__ for provider in Provider.__providers__ if provider.working],
16 default=None, help="Default provider for chat completion. (incompatible with --debug and --workers)")
17 api_parser.add_argument("--proxy", default=None, help="Default used proxy.")
14 18 api_parser.add_argument("--workers", type=int, default=None, help="Number of workers.")
15 19 api_parser.add_argument("--disable-colors", action="store_true", help="Don't use colors.")
16 20 api_parser.add_argument("--ignore-cookie-files", action="store_true", help="Don't read .har and cookie files.")
@@ -31,14 +35,15 @@ def main():
31 35 def run_api_args(args):
32 36 from g4f.api import AppConfig, run_api
33 37
34 AppConfig.set_ignore_cookie_files(
35 args.ignore_cookie_files
36 )
37 AppConfig.set_list_ignored_providers(
38 args.ignored_providers
39 )
40 AppConfig.set_g4f_api_key(
41 args.g4f_api_key
38 AppConfig.set_config(
39 ignore_cookie_files=args.ignore_cookie_files,
40 ignored_providers=args.ignored_providers,
41 g4f_api_key=args.g4f_api_key,
42 defaults={
43 "model": args.model,
44 "provider": args.provider,
45 "proxy": args.proxy
46 }
42 47 )
43 48 run_api(
44 49 bind=args.bind,
Modified g4f/requests/__init__.py +1 -1
@@ -40,7 +40,7 @@ async def get_args_from_webview(url: str) -> dict:
40 40 "Referer": window.real_url
41 41 }
42 42 cookies = [list(*cookie.items()) for cookie in window.get_cookies()]
43 cookies = dict([(name, cookie.value) for name, cookie in cookies])
43 cookies = {name: cookie.value for name, cookie in cookies}
44 44 window.destroy()
45 45 return {"headers": headers, "cookies": cookies}
46 46