openrouter-provider 0.0.3__py3-none-any.whl → 0.0.5__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.
@@ -6,6 +6,8 @@ import base64
6
6
  from io import BytesIO
7
7
  from dataclasses import dataclass
8
8
 
9
+ from openai.types.chat import ChatCompletion
10
+
9
11
 
10
12
  class Role(Enum):
11
13
  system = "system"
@@ -24,15 +26,21 @@ class ToolCall:
24
26
 
25
27
 
26
28
  class Chat_message:
27
- def __init__(self, text: str, images: list[Image.Image]=None, role: Role=Role.user, answerdBy: LLMModel=None, token :int=0, cost: float=0) -> None:
29
+ def __init__(self,
30
+ text: str,
31
+ images: list[Image.Image]=None,
32
+ role: Role=Role.user,
33
+ answerdBy: LLMModel=None,
34
+ raw_response: ChatCompletion=None
35
+ ) -> None:
28
36
  self.role = role
29
37
  self.text = text
30
38
  self.images = self._process_image(images=images)
31
- self.token = token
32
- self.cost = cost
33
39
  self.answeredBy: LLMModel = answerdBy
34
40
 
35
41
  self.tool_calls: list[ToolCall] = []
42
+ self.raw_resoonse: ChatCompletion = raw_response
43
+
36
44
 
37
45
  def __str__(self) -> str:
38
46
  # ANSI color codes for blue, green, and reset (to default)
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from .Chat_message import *
2
3
  from .Tool import tool_model
3
4
  from .LLMs import *
@@ -9,6 +10,10 @@ from dataclasses import dataclass, field, asdict
9
10
  from typing import List, Optional, Literal
10
11
  import json
11
12
 
13
+ # エラーのみ表示、詳細なトレースバック付き
14
+ logging.basicConfig(level=logging.ERROR, format="%(asctime)s - %(levelname)s - %(message)s")
15
+ logger = logging.getLogger(__name__)
16
+
12
17
 
13
18
  @dataclass
14
19
  class ProviderConfig:
@@ -21,7 +26,7 @@ class ProviderConfig:
21
26
  quantizations: Optional[List[str]] = None
22
27
  sort: Optional[Literal["price", "throughput"]] = None
23
28
  max_price: Optional[dict] = None
24
-
29
+
25
30
  def to_dict(self) -> dict:
26
31
  return {k: v for k, v in asdict(self).items() if v is not None}
27
32
 
@@ -29,17 +34,19 @@ class ProviderConfig:
29
34
  class OpenRouterProvider:
30
35
  def __init__(self) -> None:
31
36
  load_dotenv()
37
+ api_key = os.getenv("OPENROUTER_API_KEY")
38
+ if not api_key:
39
+ logger.error("OPENROUTER_API_KEY is not set in environment variables.")
32
40
  self.client = OpenAI(
33
41
  base_url="https://openrouter.ai/api/v1",
34
- api_key=os.getenv("OPENROUTER_API_KEY"),
42
+ api_key=api_key,
35
43
  )
36
44
 
37
45
  def make_prompt(self, system_prompt: Chat_message,
38
- querys: list[Chat_message]) -> list[dict]:
46
+ querys: list[Chat_message]) -> list[dict]:
39
47
  messages = [{"role": "system", "content": system_prompt.text}]
40
48
 
41
49
  for query in querys:
42
- # ----- USER -----
43
50
  if query.role == Role.user:
44
51
  if query.images is None:
45
52
  messages.append({"role": "user", "content": query.text})
@@ -48,15 +55,13 @@ class OpenRouterProvider:
48
55
  for img in query.images[:50]:
49
56
  content.append(
50
57
  {"type": "image_url",
51
- "image_url": {"url": f"data:image/jpeg;base64,{img}"}})
58
+ "image_url": {"url": f"data:image/jpeg;base64,{img}"}})
52
59
  messages.append({"role": "user", "content": content})
53
60
 
54
- # ----- ASSISTANT -----
55
61
  elif query.role == Role.ai or query.role == Role.tool:
56
62
  assistant_msg = {"role": "assistant"}
57
- assistant_msg["content"] = query.text or None # ← content は明示必須
63
+ assistant_msg["content"] = query.text or None
58
64
 
59
- # ① tool_calls を付与(あれば)
60
65
  if query.tool_calls:
61
66
  assistant_msg["tool_calls"] = [
62
67
  {
@@ -64,38 +69,44 @@ class OpenRouterProvider:
64
69
  "type": "function",
65
70
  "function": {
66
71
  "name": t.name,
67
- "arguments": t.arguments # JSON 文字列
72
+ "arguments": t.arguments
68
73
  }
69
74
  }
70
75
  for t in query.tool_calls
71
76
  ]
72
77
  messages.append(assistant_msg)
73
78
 
74
- # ② tool メッセージを assistant の直後に並べる
75
79
  for t in query.tool_calls:
76
80
  messages.append({
77
81
  "role": "tool",
78
82
  "tool_call_id": str(t.id),
79
- "content": str(t.result) # 実行結果(文字列)
83
+ "content": str(t.result)
80
84
  })
85
+
81
86
  return messages
82
87
 
88
+ def invoke(self, model: LLMModel, system_prompt: Chat_message, querys: list[Chat_message], tools: list[tool_model] = [], provider: ProviderConfig = None) -> Chat_message:
89
+ try:
90
+ messages = self.make_prompt(system_prompt, querys)
83
91
 
84
- def invoke(self, model: LLMModel, system_prompt: Chat_message, querys: list[Chat_message], tools:list[tool_model]=[], provider:ProviderConfig=None) -> Chat_message:
85
- response = self.client.chat.completions.create(
86
- model=model.name,
87
- messages=self.make_prompt(system_prompt, querys),
88
- tools=[tool.tool_definition for tool in tools],
89
- extra_body={
90
- "provider": provider.to_dict() if provider else None
91
- }
92
- )
93
- reply = Chat_message(text=response.choices[0].message.content, role=Role.ai)
94
-
95
- if response.choices[0].message.tool_calls:
96
- reply.role = Role.tool
97
- for tool in response.choices[0].message.tool_calls:
98
- reply.tool_calls.append(ToolCall(id=tool.id, name=tool.function.name, arguments=tool.function.arguments))
99
-
100
- return reply
92
+ tool_defs = [tool.tool_definition for tool in tools] if tools else None
93
+ provider_dict = provider.to_dict() if provider else None
94
+
95
+ response = self.client.chat.completions.create(
96
+ model=model.name,
97
+ messages=messages,
98
+ tools=tool_defs,
99
+ extra_body={"provider": provider_dict}
100
+ )
101
+
102
+ reply = Chat_message(text=response.choices[0].message.content, role=Role.ai, raw_response=response)
103
+
104
+ if response.choices[0].message.tool_calls:
105
+ reply.role = Role.tool
106
+ for tool in response.choices[0].message.tool_calls:
107
+ reply.tool_calls.append(ToolCall(id=tool.id, name=tool.function.name, arguments=tool.function.arguments))
108
+ return reply
101
109
 
110
+ except Exception as e:
111
+ logger.exception(f"An error occurred while invoking the model: {e.__class__.__name__}: {str(e)}")
112
+ return Chat_message(text="Fail to get response. Please see the error message.", role=Role.ai, raw_response=None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openrouter-provider
3
- Version: 0.0.3
3
+ Version: 0.0.5
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
+ __init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ OpenRouterProvider/Chat_message.py,sha256=lQd8bFp7OHOgeOrcpcVZMdkV2Mb4reUsv5Ixo6WecYY,4424
3
+ OpenRouterProvider/Chatbot_manager.py,sha256=EpLWhxx7xnRa-q7xqP2Ur9dmYb9Mzv_UF6BChwpcbYk,4357
4
+ OpenRouterProvider/LLMs.py,sha256=-0ELd6fqmdDvsdaPIElRsluiK85-Y6USwvQb2b4M8TA,2607
5
+ OpenRouterProvider/OpenRouterProvider.py,sha256=4k87D5kKNPgRJ-7qMv9oPWY7P2psrNaNOALmyPMuNsw,4397
6
+ OpenRouterProvider/Tool.py,sha256=QeeWOD2oaYjB9tjF-Jvcjd_G_qSUIuKwFgyh20Ne06I,2010
7
+ openrouter_provider-0.0.5.dist-info/METADATA,sha256=_H9lXm0ohRX57GdvJMJNIyn6pyWblQQTDHOWv7EM6GE,5995
8
+ openrouter_provider-0.0.5.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
9
+ openrouter_provider-0.0.5.dist-info/top_level.txt,sha256=I5BMEzkQFEnEYTqOY1Ktmnp7r1rrZQyeWdclKyyyHKs,28
10
+ openrouter_provider-0.0.5.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- __init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- OpenRouterProvider/Chat_message.py,sha256=EG6CGfe3qLdczehA6wkX9FWTEFdKteAKWprQ5VSRbbU,4259
3
- OpenRouterProvider/Chatbot_manager.py,sha256=EpLWhxx7xnRa-q7xqP2Ur9dmYb9Mzv_UF6BChwpcbYk,4357
4
- OpenRouterProvider/LLMs.py,sha256=-0ELd6fqmdDvsdaPIElRsluiK85-Y6USwvQb2b4M8TA,2607
5
- OpenRouterProvider/OpenRouterProvider.py,sha256=BE7O2b1iW_g8xp7tFjwgGzd6T3G96EVI4Pz69ovw4RU,3929
6
- OpenRouterProvider/Tool.py,sha256=QeeWOD2oaYjB9tjF-Jvcjd_G_qSUIuKwFgyh20Ne06I,2010
7
- openrouter_provider-0.0.3.dist-info/METADATA,sha256=iWSY6mLLjCPaWUEyt_ATUKsdKONSGp7JHjkQeJbI2UQ,5995
8
- openrouter_provider-0.0.3.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
9
- openrouter_provider-0.0.3.dist-info/top_level.txt,sha256=I5BMEzkQFEnEYTqOY1Ktmnp7r1rrZQyeWdclKyyyHKs,28
10
- openrouter_provider-0.0.3.dist-info/RECORD,,