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

XFEstudio/gpt4free

Upload bucket files as attachments instead of using render_messages

Co-authored-by: hlohaus <983577+hlohaus@users.noreply.github.com>

9c6d2a93
copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
提交于

代码差异

1 个文件 +63 -11
Modified g4f/Provider/Copilot.py +63 -11
@@ -20,7 +20,7 @@ except ImportError:
20 20 has_nodriver = False
21 21
22 22 from .base_provider import AsyncAuthedProvider, ProviderModelMixin
23 from .helper import format_prompt_max_length, render_messages
23 from .helper import format_prompt_max_length
24 24 from .openai.har_file import get_headers, get_har_files
25 25 from ..typing import AsyncResult, Messages, MediaListType
26 26 from ..errors import MissingRequirementsError, NoValidHarFileError, MissingAuthError
@@ -29,6 +29,9 @@ from ..tools.media import merge_media
29 29 from ..requests import get_nodriver
30 30 from ..image import to_bytes, is_accepted_format
31 31 from .helper import get_last_user_message
32 from ..files import get_bucket_dir
33 from ..tools.files import get_filenames
34 from pathlib import Path
32 35 from .. import debug
33 36
34 37 class Conversation(JsonConversation):
@@ -37,6 +40,16 @@ class Conversation(JsonConversation):
37 40 def __init__(self, conversation_id: str):
38 41 self.conversation_id = conversation_id
39 42
43 def extract_bucket_ids(messages: Messages) -> list[str]:
44 """Extract bucket_ids from messages content."""
45 bucket_ids = []
46 for message in messages:
47 if isinstance(message, dict) and isinstance(message.get("content"), list):
48 for content_item in message["content"]:
49 if isinstance(content_item, dict) and "bucket_id" in content_item:
50 bucket_ids.append(content_item["bucket_id"])
51 return bucket_ids
52
40 53 class Copilot(AsyncAuthedProvider, ProviderModelMixin):
41 54 label = "Microsoft Copilot"
42 55 url = "https://copilot.microsoft.com"
@@ -140,28 +153,26 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
140 153 cls._access_token = None
141 154 else:
142 155 debug.log(f"Copilot: User: {user}")
143 # Process messages to include bucket content once
144 rendered_messages = list(render_messages(messages))
145
146 156 if conversation is None:
147 157 response = await session.post(cls.conversation_url)
148 158 response.raise_for_status()
149 159 conversation_id = response.json().get("id")
150 160 conversation = Conversation(conversation_id)
151 161 if prompt is None:
152 prompt = format_prompt_max_length(rendered_messages, 10000)
162 prompt = format_prompt_max_length(messages, 10000)
153 163 debug.log(f"Copilot: Created conversation: {conversation_id}")
154 164 else:
155 165 conversation_id = conversation.conversation_id
156 166 if prompt is None:
157 prompt = get_last_user_message(rendered_messages)
167 prompt = get_last_user_message(messages)
158 168 debug.log(f"Copilot: Use conversation: {conversation_id}")
159 169 if return_conversation:
160 170 yield conversation
161 171
162 uploaded_images = []
163 # Use rendered messages for media processing to ensure consistency
164 for media, _ in merge_media(media, rendered_messages):
172 uploaded_attachments = []
173
174 # Upload regular media (images)
175 for media, _ in merge_media(media, messages):
165 176 if not isinstance(media, str):
166 177 data = to_bytes(media)
167 178 response = await session.post(
@@ -174,7 +185,48 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
174 185 )
175 186 response.raise_for_status()
176 187 media = response.json().get("url")
177 uploaded_images.append({"type":"image", "url": media})
188 uploaded_attachments.append({"type":"image", "url": media})
189
190 # Upload bucket files
191 bucket_ids = extract_bucket_ids(messages)
192 for bucket_id in bucket_ids:
193 bucket_dir = Path(get_bucket_dir(bucket_id))
194 if bucket_dir.exists():
195 filenames = get_filenames(bucket_dir)
196 for filename in filenames:
197 file_path = bucket_dir / filename
198 if file_path.exists() and file_path.is_file():
199 try:
200 with open(file_path, "rb") as f:
201 file_data = f.read()
202
203 # Determine content type based on file extension
204 content_type = "application/octet-stream"
205 if filename.endswith(".pdf"):
206 content_type = "application/pdf"
207 elif filename.endswith(".docx"):
208 content_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
209 elif filename.endswith(".txt"):
210 content_type = "text/plain"
211 elif filename.endswith(".md"):
212 content_type = "text/markdown"
213
214 response = await session.post(
215 "https://copilot.microsoft.com/c/api/attachments",
216 headers={
217 "content-type": content_type,
218 "content-length": str(len(file_data)),
219 },
220 data=file_data
221 )
222 response.raise_for_status()
223 file_url = response.json().get("url")
224 uploaded_attachments.append({"type": "file", "url": file_url, "name": filename})
225 debug.log(f"Copilot: Uploaded bucket file: {filename}")
226 except Exception as e:
227 debug.log(f"Copilot: Failed to upload bucket file {filename}: {e}")
228 else:
229 debug.log(f"Copilot: Bucket directory not found: {bucket_id}")
178 230
179 231 wss = await session.ws_connect(cls.websocket_url, timeout=3)
180 232 if "Think" in model:
@@ -186,7 +238,7 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
186 238 await wss.send(json.dumps({
187 239 "event": "send",
188 240 "conversationId": conversation_id,
189 "content": [*uploaded_images, {
241 "content": [*uploaded_attachments, {
190 242 "type": "text",
191 243 "text": prompt,
192 244 }],