openrouter-provider 1.0.6__py3-none-any.whl → 1.0.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of openrouter-provider might be problematic. Click here for more details.

openrouter/message.py CHANGED
@@ -3,6 +3,7 @@ from dataclasses import dataclass
3
3
  from enum import Enum
4
4
  from io import BytesIO
5
5
  import base64
6
+ import uuid
6
7
  from typing import Optional, Any
7
8
 
8
9
  from PIL import Image
@@ -34,8 +35,10 @@ class Message:
34
35
  images: Optional[list[Image.Image]] = None,
35
36
  role: Role = Role.user,
36
37
  answered_by: Optional[LLMModel] = None,
37
- raw_response: Optional[ChatCompletion] = None
38
+ raw_response: Optional[ChatCompletion] = None,
39
+ id: Optional[str] = None
38
40
  ) -> None:
41
+ self.id = id if id is not None else str(uuid.uuid4())
39
42
  self.role = role
40
43
  self.text = text
41
44
  self.images = self._process_image(images)
openrouter/openrouter.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
  import json
3
3
  import time
4
+ from copy import deepcopy
4
5
  from typing import Iterator, AsyncIterator
5
6
 
6
7
  from dotenv import load_dotenv
@@ -35,9 +36,57 @@ class OpenRouterClient:
35
36
  system_prompt = _base_system_prompt
36
37
  system_prompt = system_prompt.replace("[TIME]", f"{month}/{day}/{year}")
37
38
  system_prompt = system_prompt.replace("[SYSTEM_INSTRUCTION]", prompt)
38
-
39
+
39
40
  self._system_prompt = Message(text=system_prompt, role=Role.system)
40
-
41
+
42
+ def _execute_tools(self, reply: Message, tools: list[tool_model]) -> Message:
43
+ if not reply.tool_calls:
44
+ return reply
45
+
46
+ reply_copy = deepcopy(reply)
47
+
48
+ for requested_tool in reply_copy.tool_calls:
49
+ args = requested_tool.arguments
50
+ if isinstance(args, str):
51
+ args = json.loads(args)
52
+
53
+ for tool in tools:
54
+ if tool.name == requested_tool.name:
55
+ result = tool(**args)
56
+ requested_tool.result = result
57
+ break
58
+
59
+ return reply_copy
60
+
61
+ def execute_tool(self, reply: Message, tool_index: int) -> Message:
62
+ if not reply.tool_calls:
63
+ return reply
64
+
65
+ if tool_index < 0 or tool_index >= len(reply.tool_calls):
66
+ raise IndexError(f"Tool index {tool_index} is out of range. Available tools: {len(reply.tool_calls)}")
67
+
68
+ requested_tool = reply.tool_calls[tool_index]
69
+
70
+ args = requested_tool.arguments
71
+ if isinstance(args, str):
72
+ args = json.loads(args)
73
+
74
+ all_tools = self.tools
75
+ for tool in all_tools:
76
+ if tool.name == requested_tool.name:
77
+ result = tool(**args)
78
+ requested_tool.result = result
79
+ break
80
+ else:
81
+ raise ValueError(f"Tool '{requested_tool.name}' not found in registered tools")
82
+
83
+ for i, msg in enumerate(self._memory):
84
+ if msg.id == reply.id:
85
+ self._memory[i] = reply
86
+ break
87
+
88
+ return reply
89
+
41
90
  def clear_memory(self) -> None:
42
91
  self._memory = []
43
92
 
@@ -80,55 +129,38 @@ class OpenRouterClient:
80
129
  def invoke(
81
130
  self,
82
131
  model: LLMModel,
83
- query: Message,
132
+ query: Message = None,
84
133
  tools: list[tool_model] = None,
85
- max_tools_loop: int = 3,
86
134
  provider: ProviderConfig = None,
87
- temperature: float = 0.3
135
+ temperature: float = 0.3,
136
+ auto_tool_exec: bool = True
88
137
  ) -> Message:
89
138
  tools = tools or []
90
- self._memory.append(query)
139
+ if query is not None:
140
+ self._memory.append(query)
91
141
  client = OpenRouterProvider()
92
-
93
- for i in range(max_tools_loop):
94
- reply = client.invoke(
95
- model=model,
96
- temperature=temperature,
97
- system_prompt=self._system_prompt,
98
- querys=self._memory,
99
- tools=self.tools + tools,
100
- provider=provider,
101
- )
102
- reply.answered_by = model
103
- self._memory.append(reply)
104
142
 
105
- # Execute tools
106
- if reply.tool_calls:
107
- for requested_tool in reply.tool_calls:
108
- args = requested_tool.arguments
109
- if isinstance(args, str):
110
- args = json.loads(args)
111
-
112
- for tool in (self.tools + tools):
113
- if tool.name == requested_tool.name:
114
- result = tool(**args)
115
- requested_tool.result = result
116
- break
117
- else:
118
- return reply
119
-
120
- # If normal reply, do nothing
121
- else:
122
- break
123
-
124
- # If over max execution, send message without tools
125
- else:
143
+ reply = client.invoke(
144
+ model=model,
145
+ temperature=temperature,
146
+ system_prompt=self._system_prompt,
147
+ querys=self._memory,
148
+ tools=self.tools + tools,
149
+ provider=provider,
150
+ )
151
+ reply.answered_by = model
152
+ self._memory.append(reply)
153
+
154
+ if auto_tool_exec and reply.tool_calls:
155
+ reply = self._execute_tools(reply, self.tools + tools)
156
+ self._memory[-1] = reply
157
+
126
158
  reply = client.invoke(
127
159
  model=model,
128
160
  temperature=temperature,
129
161
  system_prompt=self._system_prompt,
130
162
  querys=self._memory,
131
- provider=provider,
163
+ provider=provider
132
164
  )
133
165
  reply.answered_by = model
134
166
  self._memory.append(reply)
@@ -165,13 +197,15 @@ class OpenRouterClient:
165
197
  async def async_invoke(
166
198
  self,
167
199
  model: LLMModel,
168
- query: Message,
200
+ query: Message = None,
169
201
  tools: list[tool_model] = None,
170
202
  provider: ProviderConfig = None,
171
- temperature: float = 0.3
203
+ temperature: float = 0.3,
204
+ auto_tool_exec: bool = True
172
205
  ) -> Message:
173
206
  tools = tools or []
174
- self._memory.append(query)
207
+ if query is not None:
208
+ self._memory.append(query)
175
209
  client = OpenRouterProvider()
176
210
  reply = await client.async_invoke(
177
211
  model=model,
@@ -184,19 +218,8 @@ class OpenRouterClient:
184
218
  reply.answered_by = model
185
219
  self._memory.append(reply)
186
220
 
187
- if reply.tool_calls:
188
- for requested_tool in reply.tool_calls:
189
- args = requested_tool.arguments
190
- if isinstance(args, str):
191
- args = json.loads(args)
192
-
193
- for tool in (self.tools + tools):
194
- if tool.name == requested_tool.name:
195
- result = tool(**args)
196
- requested_tool.result = result
197
- break
198
- else:
199
- return reply
221
+ if auto_tool_exec and reply.tool_calls:
222
+ reply = self._execute_tools(reply, self.tools + tools)
200
223
 
201
224
  reply = await client.async_invoke(
202
225
  model=model,
@@ -261,3 +284,4 @@ class OpenRouterClient:
261
284
  self._memory.append(Message(text=reply.model_dump_json(), role=Role.ai, answered_by=model))
262
285
 
263
286
  return reply
287
+
@@ -122,6 +122,8 @@ class OpenRouterProvider:
122
122
  for tool in response.choices[0].message.tool_calls:
123
123
  reply.tool_calls.append(ToolCall(id=tool.id, name=tool.function.name, arguments=tool.function.arguments))
124
124
  return reply
125
+
126
+
125
127
 
126
128
  def invoke_stream(
127
129
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openrouter-provider
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: This is an unofficial wrapper of OpenRouter.
5
5
  Author-email: Keisuke Miyamto <aichiboyhighschool@gmail.com>
6
6
  Requires-Python: >=3.7
@@ -0,0 +1,10 @@
1
+ openrouter/__init__.py,sha256=xuIzdm8-l3Tmc-zrNIXTicv05c9HCMxTS9xynKpWK-Q,123
2
+ openrouter/llms.py,sha256=zmujFW5BmQA0Fm6z8skuO3ipLpaUMy1VBZxYkPE9OcM,3391
3
+ openrouter/message.py,sha256=ESI4YT6x0TuPZ0AY29ZPlBCv72KrQad1-IeNmrfGD0w,2978
4
+ openrouter/openrouter.py,sha256=p6Wa_IgYDZuT5QzNpTIC6Cz-Sb6z3llrejtqNK980FY,8955
5
+ openrouter/openrouter_provider.py,sha256=_Rt85X5pJ1IGbJeITfnzEG0QSp0qTo_PrDWIqtbd0xg,8577
6
+ openrouter/tool.py,sha256=tUUNLosz1XhzPIwY1zHXWNM3ePs7hcVD1a_W5hWTCWk,1975
7
+ openrouter_provider-1.0.8.dist-info/METADATA,sha256=-EKwC71xJK_1YZxPWh0EtSe198HnRAS4sfSygqVHlkU,11503
8
+ openrouter_provider-1.0.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ openrouter_provider-1.0.8.dist-info/top_level.txt,sha256=0jnlCcRirGeYZLm5ZbWQRUonIp4tTPl_9mq-ds_1SEo,11
10
+ openrouter_provider-1.0.8.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- openrouter/__init__.py,sha256=xuIzdm8-l3Tmc-zrNIXTicv05c9HCMxTS9xynKpWK-Q,123
2
- openrouter/llms.py,sha256=zmujFW5BmQA0Fm6z8skuO3ipLpaUMy1VBZxYkPE9OcM,3391
3
- openrouter/message.py,sha256=0q0OYdTl3f1TOx79TJRwPYyFuTxoYI9tSCpQN-N8G-A,2870
4
- openrouter/openrouter.py,sha256=J74xqt3ycpD_RUhScEzX3vKc4zfwaJE6Wq3SLGDO6Kc,8368
5
- openrouter/openrouter_provider.py,sha256=w6isS1VX7iMf71zwQ5tMv7v5X0yeMbLF6vqimOrB724,8567
6
- openrouter/tool.py,sha256=tUUNLosz1XhzPIwY1zHXWNM3ePs7hcVD1a_W5hWTCWk,1975
7
- openrouter_provider-1.0.6.dist-info/METADATA,sha256=92TvxKqv7j2j3s0kahWhQKe3pc6VUv5t6-h7gH4onrs,11503
8
- openrouter_provider-1.0.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
- openrouter_provider-1.0.6.dist-info/top_level.txt,sha256=0jnlCcRirGeYZLm5ZbWQRUonIp4tTPl_9mq-ds_1SEo,11
10
- openrouter_provider-1.0.6.dist-info/RECORD,,