返回提交历史
Modified
g4f-go/fetch-python.sh
+58
-58
Modified
g4f-go/process.go
+1
-5
Modified
g4f-go/runtime.go
+2
-4
Modified
g4f/Provider/__init__.py
+6
-0
Modified
g4f/providers/any_provider.py
+1
-5
XFEstudio/gpt4free
Fix go build
860489e7
代码差异
5 个文件
+68
-72
@@ -106,66 +106,66 @@ do_platform() {
106
106
*) echo " WARNING: no wheel tag for $name; runtime will need network on first run" >&2; tag="" ;;
107
107
esac
108
108
mkdir -p "$dir/wheels"
109
if [ -n "$tag" ]; then
110
# Windows pip can't read process-substitution FDs from its subprocess, so
111
# write the version floors to a real file once per platform.
112
local floors="$dir/wheels.floors"
113
printf '%s\n' "$WHEEL_FLOORS" > "$floors"
114
# Full dependency resolution (no --no-deps) so the runtime's offline
115
# `pip install g4f` finds every transitive wheel it needs.
116
# brotli is optional in g4f and has no cp314 wheel for win_arm64;
117
# fall back to fetching everything else if a single dep is unavailable.
118
if ! python3 -m pip download \
119
-r "$G4F_SRC/requirements-min.txt" \
120
--constraint "$floors" \
121
--only-binary=:all: \
122
--python-version "$PYVER" --implementation cp --abi "cp$(echo "$PYVER" | tr -d '.')" \
123
--platform "$tag" \
124
-d "$dir/wheels" -q 2>"$dir/pip.err"; then
125
echo " WARNING: full wheel set for $name not available; retrying without brotli (optional dep)" >&2
126
grep -v '^brotli$' "$G4F_SRC/requirements-min.txt" > "$dir/req-nobrotli.txt"
127
python3 -m pip download \
128
-r "$dir/req-nobrotli.txt" \
129
--constraint "$floors" \
130
--only-binary=:all: \
131
--python-version "$PYVER" --implementation cp --abi "cp$(echo "$PYVER" | tr -d '.')" \
132
--platform "$tag" \
133
-d "$dir/wheels" -q 2>>"$dir/pip.err" || {
134
echo " WARNING: wheel download for $name failed; runtime will need network on first run" >&2
135
}
136
fi
137
# Belt-and-braces: drop any wheel whose Requires-Python metadata excludes
138
# our interpreter. The --constraint above prevents this at resolve time;
139
# this catches stale wheels (e.g. copied in from wheels-cache) and covers
140
# ancient pure-python releases like aiohttp 0.13.1.
141
python3 - "$dir/wheels" "$PYVER" <<'PY' || true
142
import glob, os, sys, zipfile
143
from packaging.specifiers import SpecifierSet
144
from packaging.version import Version
145
want_v = Version(sys.argv[2])
146
for whl in glob.glob(os.path.join(sys.argv[1], "*.whl")):
147
try:
148
with zipfile.ZipFile(whl) as z:
149
meta = next((n for n in z.namelist() if n.endswith(".dist-info/METADATA")), None)
150
if not meta:
151
continue
152
txt = z.read(meta).decode("utf-8", "replace")
153
rp = next((l.split(":", 1)[1].strip() for l in txt.splitlines()
154
if l.lower().startswith("requires-python:")), None)
155
if rp and not SpecifierSet(rp).contains(want_v):
156
print(f" removing {os.path.basename(whl)} (Requires-Python {rp} excludes {sys.argv[2]})")
157
os.remove(whl)
158
except Exception as e:
159
print(f" skip check {os.path.basename(whl)}: {e}")
160
PY
161
fi
109
# if [ -n "$tag" ]; then
110
# # Windows pip can't read process-substitution FDs from its subprocess, so
111
# # write the version floors to a real file once per platform.
112
# local floors="$dir/wheels.floors"
113
# printf '%s\n' "$WHEEL_FLOORS" > "$floors"
114
# # Full dependency resolution (no --no-deps) so the runtime's offline
115
# # `pip install g4f` finds every transitive wheel it needs.
116
# # brotli is optional in g4f and has no cp314 wheel for win_arm64;
117
# # fall back to fetching everything else if a single dep is unavailable.
118
# if ! python3 -m pip download \
119
# -r "$G4F_SRC/requirements-min.txt" \
120
# --constraint "$floors" \
121
# --only-binary=:all: \
122
# --python-version "$PYVER" --implementation cp --abi "cp$(echo "$PYVER" | tr -d '.')" \
123
# --platform "$tag" \
124
# -d "$dir/wheels" -q 2>"$dir/pip.err"; then
125
# echo " WARNING: full wheel set for $name not available; retrying without brotli (optional dep)" >&2
126
# grep -v '^brotli$' "$G4F_SRC/requirements-min.txt" > "$dir/req-nobrotli.txt"
127
# python3 -m pip download \
128
# -r "$dir/req-nobrotli.txt" \
129
# --constraint "$floors" \
130
# --only-binary=:all: \
131
# --python-version "$PYVER" --implementation cp --abi "cp$(echo "$PYVER" | tr -d '.')" \
132
# --platform "$tag" \
133
# -d "$dir/wheels" -q 2>>"$dir/pip.err" || {
134
# echo " WARNING: wheel download for $name failed; runtime will need network on first run" >&2
135
# }
136
# fi
137
# # Belt-and-braces: drop any wheel whose Requires-Python metadata excludes
138
# # our interpreter. The --constraint above prevents this at resolve time;
139
# # this catches stale wheels (e.g. copied in from wheels-cache) and covers
140
# # ancient pure-python releases like aiohttp 0.13.1.
141
# python3 - "$dir/wheels" "$PYVER" <<'PY' || true
142
# import glob, os, sys, zipfile
143
# from packaging.specifiers import SpecifierSet
144
# from packaging.version import Version
145
# want_v = Version(sys.argv[2])
146
# for whl in glob.glob(os.path.join(sys.argv[1], "*.whl")):
147
# try:
148
# with zipfile.ZipFile(whl) as z:
149
# meta = next((n for n in z.namelist() if n.endswith(".dist-info/METADATA")), None)
150
# if not meta:
151
# continue
152
# txt = z.read(meta).decode("utf-8", "replace")
153
# rp = next((l.split(":", 1)[1].strip() for l in txt.splitlines()
154
# if l.lower().startswith("requires-python:")), None)
155
# if rp and not SpecifierSet(rp).contains(want_v):
156
# print(f" removing {os.path.basename(whl)} (Requires-Python {rp} excludes {sys.argv[2]})")
157
# os.remove(whl)
158
# except Exception as e:
159
# print(f" skip check {os.path.basename(whl)}: {e}")
160
# PY
161
# fi
162
162
163
163
# 3) Merge g4f package + wheels so the interpreter is self-contained.
164
rsync -a --exclude='.git' --exclude='g4f-go' --exclude='g4f.dev' --exclude='g4f.egg-info' \
165
"$G4F_SRC/g4f" "$dir/python-home/g4f"
166
rsync -a --exclude='.git' --exclude='g4f-go' --exclude='g4f.dev' --exclude='g4f.egg-info' \
167
"$G4F_SRC/requirements-min.txt" "$dir/python-home/requirements-min.txt"
168
cp -n "$WORK/wheels-cache/"*.whl "$dir/wheels/" 2>/dev/null || true
164
# rsync -a --exclude='.git' --exclude='g4f-go' --exclude='g4f.dev' --exclude='g4f.egg-info' \
165
# "$G4F_SRC/g4f" "$dir/python-home/g4f"
166
# rsync -a --exclude='.git' --exclude='g4f-go' --exclude='g4f.dev' --exclude='g4f.egg-info' \
167
# "$G4F_SRC/requirements-min.txt" "$dir/python-home/requirements-min.txt"
168
# cp -n "$WORK/wheels-cache/"*.whl "$dir/wheels/" 2>/dev/null || true
169
169
170
170
# 4) Pre-stamp install so first run is instant.
171
171
mkdir -p "$dir/.g4f-runtime"
@@ -132,11 +132,7 @@ func extractZip(r io.ReaderAt, size int64, dest string) error {
132
132
func pythonExecutable(binDir string) string {
133
133
home := filepath.Join(binDir, "python-home")
134
134
if runtime.GOOS == "windows" {
135
exe := filepath.Join(home, "python.exe")
136
if fi, err := os.Stat(exe); err == nil && !fi.IsDir() {
137
return exe
138
}
139
return filepath.Join(binDir, "python.exe")
135
return filepath.Join(home, "python.exe")
140
136
}
141
137
exe := filepath.Join(home, "bin", "python")
142
138
if fi, err := os.Stat(exe); err == nil && !fi.IsDir() {
@@ -160,8 +160,8 @@ func installG4F(binDir, exe string, start time.Time) error {
160
160
fmt.Printf("Installing gpt4free into the embedded Python runtime...\n")
161
161
code, err := runPython(noSignalCtx(), exe, []string{
162
162
"-m", "pip", "install",
163
"--no-input", "--no-index", "--find-links", "wheels",
164
"--no-cache-dir", "g4f",
163
"--no-input",
164
"--no-cache-dir", "g4f[slim]",
165
165
}, pipEnv(binDir)...)
166
166
if err != nil || code != 0 {
167
167
return fmt.Errorf("pip install g4f failed (exit %d): %w", code, err)
@@ -192,8 +192,6 @@ func pipEnv(binDir string) []string {
192
192
"PYTHONNOUSERSITE=1",
193
193
"PYTHONDONTWRITEBYTECODE=1",
194
194
"PYTHONUTF8=1",
195
"PIP_NO_INDEX=1",
196
"PIP_FIND_LINKS=" + filepath.Join(binDir, "wheels"),
197
195
"PYTHONPATH=" + lib,
198
196
}
199
197
}
@@ -117,6 +117,12 @@ def _resolve_provider(name: str) -> ProviderType:
117
117
from g4f.Provider.needs_auth.FenayAI import FenayAI
118
118
119
119
return FenayAI
120
elif name == "G4FSpace":
121
from ..client.factory import AbstractClientFactory
122
_loaded_providers[name] = AbstractClientFactory.create_provider(
123
None, "default"
124
)
125
return _loaded_providers[name]
120
126
elif name == "GLM":
121
127
from g4f.Provider.glm import GLM
122
128
@@ -4,11 +4,9 @@ import os
4
4
import re
5
5
import json
6
6
from ..typing import AsyncResult, Messages, MediaListType, Union
7
from ..errors import ModelNotFoundError
8
7
from ..image import is_data_an_audio
9
8
from ..providers.retry_provider import RotatedProvider
10
9
from ..providers.config_provider import RouterConfig, ConfigModelProvider
11
from ..client.factory import AbstractClientFactory
12
10
from ..Provider import __getattr__
13
11
from .base_provider import (
14
12
AsyncGeneratorProvider,
@@ -525,9 +523,7 @@ class AnyProvider(AsyncGeneratorProvider, AnyModelProviderMixin):
525
523
providers.sort(key=lambda p: bool(getattr(p, "needs_auth", False)))
526
524
527
525
if len(providers) == 0:
528
provider: AsyncGeneratorProvider = AbstractClientFactory.create_provider(
529
None, "default"
530
)
526
provider: AsyncGeneratorProvider = __getattr__("G4FSpace")
531
527
async for chunk in provider.create_async_generator(
532
528
model, messages, stream=stream, media=media, api_key=api_key, **kwargs
533
529
):