HowdenLLM 1.6.2__tar.gz → 1.7.0__tar.gz
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.
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/manager.py +3 -1
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/providers/base_provider.py +1 -1
- howdenllm-1.7.0/HowdenLLM/providers/provider_anthropic.py +42 -0
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/providers/provider_openai.py +24 -5
- {howdenllm-1.6.2 → howdenllm-1.7.0}/PKG-INFO +1 -1
- {howdenllm-1.6.2 → howdenllm-1.7.0}/pyproject.toml +1 -1
- howdenllm-1.6.2/HowdenLLM/providers/provider_anthropic.py +0 -27
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/__init__.py +0 -0
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/providers/__init__.py +0 -0
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/providers/known_providers.py +0 -0
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/providers/provider_factory.py +0 -0
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/providers/provider_huggingface.py +0 -0
- {howdenllm-1.6.2 → howdenllm-1.7.0}/HowdenLLM/providers/provider_meta.py +0 -0
- {howdenllm-1.6.2 → howdenllm-1.7.0}/README.md +0 -0
|
@@ -35,6 +35,7 @@ class LLM:
|
|
|
35
35
|
provider_and_model: str,
|
|
36
36
|
template: Template,
|
|
37
37
|
use_web_search_tool: bool,
|
|
38
|
+
upload_attachment: str|None,
|
|
38
39
|
system: str = None,
|
|
39
40
|
name: str = None
|
|
40
41
|
):
|
|
@@ -53,6 +54,7 @@ class LLM:
|
|
|
53
54
|
self.system: str = system
|
|
54
55
|
self.provider = ProviderFactory.create(self.provider_name)
|
|
55
56
|
self.use_web_search_tool = use_web_search_tool
|
|
57
|
+
self.upload_attachment = upload_attachment
|
|
56
58
|
self.hashed = self.compute_hash(self.input_params)
|
|
57
59
|
|
|
58
60
|
self.total_input_tokens = 0
|
|
@@ -87,7 +89,7 @@ class LLM:
|
|
|
87
89
|
input_tokens = self._count_tokens(input_text)
|
|
88
90
|
|
|
89
91
|
# --- run model ---
|
|
90
|
-
output = self.provider.complete(self.system, prompt, self.model, self.use_web_search_tool)
|
|
92
|
+
output = self.provider.complete(self.system, prompt, self.model, self.use_web_search_tool,self.upload_attachment)
|
|
91
93
|
|
|
92
94
|
# --- count output tokens ---
|
|
93
95
|
output_tokens = self._count_tokens(output)
|
|
@@ -3,5 +3,5 @@ from .provider_meta import ProviderMeta
|
|
|
3
3
|
|
|
4
4
|
class BaseProvider(ABC, metaclass=ProviderMeta):
|
|
5
5
|
@abstractmethod
|
|
6
|
-
def complete(self, system: str, prompt: str, model: str, use_web_search_tool: bool) -> str:
|
|
6
|
+
def complete(self, system: str, prompt: str, model: str, use_web_search_tool: bool, upload_attachment: str|None) -> str:
|
|
7
7
|
pass
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from HowdenLLM.providers.base_provider import BaseProvider
|
|
3
|
+
from anthropic import Anthropic
|
|
4
|
+
from .known_providers import KnownProviders
|
|
5
|
+
|
|
6
|
+
class AnthropicProvider(BaseProvider, ABC):
|
|
7
|
+
provider = KnownProviders.Anthropic
|
|
8
|
+
|
|
9
|
+
def __init__(self,client: Anthropic):
|
|
10
|
+
self.client = client
|
|
11
|
+
|
|
12
|
+
def complete(self, system: str, prompt: str, model: str, use_web_search_tool: bool, upload_attachment: str) -> str:
|
|
13
|
+
|
|
14
|
+
if use_web_search_tool:
|
|
15
|
+
tools=[{"type": "web_search_20260209","name": "web_search","max_uses": 5}]
|
|
16
|
+
else:
|
|
17
|
+
tools = []
|
|
18
|
+
|
|
19
|
+
if model in ["claude-opus-4-6","claude-opus-4-5-20251101","claude-sonnet-4-6","claude-sonnet-4-5-20250929"]:
|
|
20
|
+
message = self.client.messages.create(
|
|
21
|
+
model=model,
|
|
22
|
+
system=system,
|
|
23
|
+
messages=[
|
|
24
|
+
{"role": "user","content": prompt}
|
|
25
|
+
],
|
|
26
|
+
max_tokens=16000,
|
|
27
|
+
temperature=0.0,
|
|
28
|
+
tools=tools,
|
|
29
|
+
stream=False,
|
|
30
|
+
# thinking={"type": "adaptive"},
|
|
31
|
+
# output_config={"effort": "high"}, # or max, medium, low
|
|
32
|
+
)
|
|
33
|
+
else:
|
|
34
|
+
raise Exception(f"Unsupported model: {model}")
|
|
35
|
+
|
|
36
|
+
# print(f"Content: {message}")
|
|
37
|
+
clean_response = "\n".join(
|
|
38
|
+
block.text for block in message.content if block.type == "text"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
return clean_response
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
from abc import ABC
|
|
2
|
+
|
|
3
|
+
from sympy.codegen.ast import continue_
|
|
4
|
+
|
|
2
5
|
from HowdenLLM.providers.base_provider import BaseProvider
|
|
3
6
|
from openai import OpenAI
|
|
4
7
|
from .known_providers import KnownProviders
|
|
@@ -9,7 +12,7 @@ class OpenAIProvider(BaseProvider, ABC):
|
|
|
9
12
|
def __init__(self,client: OpenAI):
|
|
10
13
|
self.client = client
|
|
11
14
|
|
|
12
|
-
def complete(self, system: str, prompt: str, model: str, use_web_search_tool: bool) -> str:
|
|
15
|
+
def complete(self, system: str, prompt: str, model: str, use_web_search_tool: bool, upload_attachment: str|None) -> str:
|
|
13
16
|
|
|
14
17
|
if use_web_search_tool:
|
|
15
18
|
tools = [
|
|
@@ -18,13 +21,29 @@ class OpenAIProvider(BaseProvider, ABC):
|
|
|
18
21
|
else:
|
|
19
22
|
tools = None
|
|
20
23
|
|
|
24
|
+
if upload_attachment:
|
|
25
|
+
with open(upload_attachment, "rb") as f:
|
|
26
|
+
uploaded = self.client.files.create(
|
|
27
|
+
file=f,
|
|
28
|
+
purpose="user_data",
|
|
29
|
+
)
|
|
30
|
+
input=[
|
|
31
|
+
{"role": "system", "content": system},
|
|
32
|
+
{"role": "user", "content": [
|
|
33
|
+
{"type": "input_text", "text": prompt},
|
|
34
|
+
{"type": "input_file", "file_id": uploaded.id},
|
|
35
|
+
]}
|
|
36
|
+
]
|
|
37
|
+
else:
|
|
38
|
+
input=[
|
|
39
|
+
{"role": "system", "content": system},
|
|
40
|
+
{"role": "user", "content": prompt}
|
|
41
|
+
]
|
|
42
|
+
|
|
21
43
|
if model in ["gpt-5", "gpt-5.2", "gpt-5-mini", "gpt-5.4-mini", "gpt-5-nano"]:
|
|
22
44
|
response = self.client.responses.create(
|
|
23
45
|
model=model,
|
|
24
|
-
input=
|
|
25
|
-
{"role": "system", "content": system},
|
|
26
|
-
{"role": "user", "content": prompt}
|
|
27
|
-
],
|
|
46
|
+
input=input,
|
|
28
47
|
tools=tools,
|
|
29
48
|
max_output_tokens=16000
|
|
30
49
|
)
|
|
@@ -14,7 +14,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
14
14
|
|
|
15
15
|
[tool.poetry]
|
|
16
16
|
name = "HowdenLLM"
|
|
17
|
-
version = "1.
|
|
17
|
+
version = "1.7.0"
|
|
18
18
|
description = "A simple configuration manager with Pydantic and JSON export."
|
|
19
19
|
authors = [ "JesperThoftIllemannJ <jesper.jaeger@howdendanmark.dk>",]
|
|
20
20
|
readme = "README.md"
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
from HowdenLLM.providers.base_provider import BaseProvider
|
|
3
|
-
from anthropic import Anthropic
|
|
4
|
-
from .known_providers import KnownProviders
|
|
5
|
-
|
|
6
|
-
class AnthropicProvider(BaseProvider, ABC):
|
|
7
|
-
provider = KnownProviders.Anthropic
|
|
8
|
-
|
|
9
|
-
def __init__(self,client: Anthropic):
|
|
10
|
-
self.client = client
|
|
11
|
-
|
|
12
|
-
def complete(self, system: str, prompt: str, model: str, use_web_search_tool: bool) -> str:
|
|
13
|
-
if model in ["claude-opus-4-6","claude-sonnet-4-6"]:
|
|
14
|
-
message = self.client.messages.create(
|
|
15
|
-
model=model,
|
|
16
|
-
system=system,
|
|
17
|
-
messages=[
|
|
18
|
-
{"role": "user","content": prompt}
|
|
19
|
-
],
|
|
20
|
-
max_tokens=16000,
|
|
21
|
-
temperature=0.0
|
|
22
|
-
|
|
23
|
-
)
|
|
24
|
-
else:
|
|
25
|
-
raise Exception(f"Unsupported model: {model}")
|
|
26
|
-
|
|
27
|
-
return message.content[0].text
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|