llm-codegen-research 2.13__tar.gz → 2.14__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.
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/PKG-INFO +1 -1
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/__init__.py +10 -1
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/openai_tool.py +77 -7
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_codegen_research.egg-info/PKG-INFO +1 -1
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/LICENSE +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/README.md +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/pyproject.toml +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/setup.cfg +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/__init__.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/__init__.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/classes.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/__init__.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/code_data.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/javascript.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/python.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/rust.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/regexes.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/decorators.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/defaults.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/enums.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/json_utils.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/__init__.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/anthropic.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/base.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/deepseek.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/mistral.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/nscale.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/openai.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/protocol.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/together.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/generate.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/prompts.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/py.typed +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/scripts/test_cuda.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/timeout.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_codegen_research.egg-info/SOURCES.txt +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_codegen_research.egg-info/dependency_links.txt +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_codegen_research.egg-info/entry_points.txt +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_codegen_research.egg-info/requires.txt +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_codegen_research.egg-info/top_level.txt +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/tests/test_enums.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/tests/test_json_utils.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/tests/test_llm_api.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/tests/test_llm_local.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/tests/test_llm_tool.py +0 -0
- {llm_codegen_research-2.13 → llm_codegen_research-2.14}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llm-codegen-research
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.14
|
|
4
4
|
Summary: Useful classes and methods for researching code-generation by LLMs.
|
|
5
5
|
Author-email: Lukas Twist <itsluketwist@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/itsluketwist/llm-codegen-research
|
|
@@ -6,7 +6,12 @@ from llm_cgr.llm.clients.deepseek import DeepSeek_LLM
|
|
|
6
6
|
from llm_cgr.llm.clients.mistral import Mistral_LLM
|
|
7
7
|
from llm_cgr.llm.clients.nscale import Nscale_LLM
|
|
8
8
|
from llm_cgr.llm.clients.openai import OpenAI_LLM
|
|
9
|
-
from llm_cgr.llm.clients.openai_tool import
|
|
9
|
+
from llm_cgr.llm.clients.openai_tool import (
|
|
10
|
+
MAX_TOOL_CALLS,
|
|
11
|
+
MAX_TOOL_ITERATIONS,
|
|
12
|
+
OpenAI_Tool_LLM,
|
|
13
|
+
Tool,
|
|
14
|
+
)
|
|
10
15
|
from llm_cgr.llm.clients.protocol import GenerationProtocol
|
|
11
16
|
from llm_cgr.llm.clients.together import TogetherAI_LLM
|
|
12
17
|
|
|
@@ -29,6 +34,8 @@ def get_llm(
|
|
|
29
34
|
max_tokens: int | None = None,
|
|
30
35
|
provider: str | None = None,
|
|
31
36
|
tools: list[Tool] | None = None,
|
|
37
|
+
max_tool_iterations: int = MAX_TOOL_ITERATIONS,
|
|
38
|
+
max_tool_calls: int = MAX_TOOL_CALLS,
|
|
32
39
|
) -> GenerationProtocol:
|
|
33
40
|
"""
|
|
34
41
|
Initialise the correct LLM client for the given model.
|
|
@@ -63,6 +70,8 @@ def get_llm(
|
|
|
63
70
|
temperature=temperature,
|
|
64
71
|
top_p=top_p,
|
|
65
72
|
max_tokens=max_tokens,
|
|
73
|
+
max_tool_iterations=max_tool_iterations,
|
|
74
|
+
max_tool_calls=max_tool_calls,
|
|
66
75
|
)
|
|
67
76
|
|
|
68
77
|
return llm_class(
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/openai_tool.py
RENAMED
|
@@ -10,8 +10,11 @@ from openai.types.responses import ResponseFunctionToolCall, ResponseInputItemPa
|
|
|
10
10
|
from llm_cgr.llm.clients.openai import OpenAI_LLM
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
# maximum
|
|
14
|
-
MAX_TOOL_ITERATIONS: int =
|
|
13
|
+
# maximum tool-call rounds allowed within a single generate() or chat() call
|
|
14
|
+
MAX_TOOL_ITERATIONS: int = 5
|
|
15
|
+
|
|
16
|
+
# maximum total tool calls allowed across the lifetime of a client instance
|
|
17
|
+
MAX_TOOL_CALLS: int = 10
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
@dataclass
|
|
@@ -51,11 +54,17 @@ class OpenAI_Tool_LLM(OpenAI_LLM):
|
|
|
51
54
|
temperature: float | None = None,
|
|
52
55
|
top_p: float | None = None,
|
|
53
56
|
max_tokens: int | None = None,
|
|
57
|
+
max_tool_iterations: int = MAX_TOOL_ITERATIONS,
|
|
58
|
+
max_tool_calls: int = MAX_TOOL_CALLS,
|
|
54
59
|
) -> None:
|
|
55
60
|
"""
|
|
56
61
|
Initialise the OpenAI tool client.
|
|
57
62
|
|
|
58
63
|
Requires the OPENAI_API_KEY environment variable to be set.
|
|
64
|
+
max_tool_iterations caps tool-call rounds within a single request.
|
|
65
|
+
max_tool_calls caps the cumulative total across all requests on this
|
|
66
|
+
instance. When either limit is reached, the model is sent a message
|
|
67
|
+
asking it to answer immediately without any further tool calls.
|
|
59
68
|
"""
|
|
60
69
|
super().__init__(
|
|
61
70
|
model=model,
|
|
@@ -65,6 +74,8 @@ class OpenAI_Tool_LLM(OpenAI_LLM):
|
|
|
65
74
|
max_tokens=max_tokens,
|
|
66
75
|
)
|
|
67
76
|
self._tools = tools
|
|
77
|
+
self._max_tool_iterations = max_tool_iterations
|
|
78
|
+
self._max_tool_calls = max_tool_calls
|
|
68
79
|
# cumulative count of individual tool calls made by this instance
|
|
69
80
|
self._tool_calls: int = 0
|
|
70
81
|
|
|
@@ -90,6 +101,43 @@ class OpenAI_Tool_LLM(OpenAI_LLM):
|
|
|
90
101
|
"parameters": tool.parameters,
|
|
91
102
|
}
|
|
92
103
|
|
|
104
|
+
def _force_final_answer(
|
|
105
|
+
self,
|
|
106
|
+
current_input: list[Any],
|
|
107
|
+
model: str,
|
|
108
|
+
temperature: float | None,
|
|
109
|
+
top_p: float | None,
|
|
110
|
+
max_tokens: int | None,
|
|
111
|
+
) -> str:
|
|
112
|
+
"""Force the model to produce a text answer after a limit is reached.
|
|
113
|
+
|
|
114
|
+
Appends a user message telling the model it has used all its allowed
|
|
115
|
+
tool calls, then calls the API one final time without any tools so the
|
|
116
|
+
model cannot make further calls.
|
|
117
|
+
|
|
118
|
+
Returns the model's final text response.
|
|
119
|
+
"""
|
|
120
|
+
# tell the model it must answer now — no more tool calls are allowed
|
|
121
|
+
current_input.append(
|
|
122
|
+
self._build_message(
|
|
123
|
+
role="user",
|
|
124
|
+
content=(
|
|
125
|
+
"You have reached the maximum number of tool calls allowed. "
|
|
126
|
+
"Please provide your final answer now based on the information "
|
|
127
|
+
"you have gathered, without calling any more tools."
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
response = self._client.responses.create(
|
|
132
|
+
input=cast(list[ResponseInputItemParam], current_input),
|
|
133
|
+
model=model,
|
|
134
|
+
temperature=temperature if temperature is not None else openai.omit,
|
|
135
|
+
top_p=top_p if top_p is not None else openai.omit,
|
|
136
|
+
max_output_tokens=max_tokens if max_tokens is not None else openai.omit,
|
|
137
|
+
# no tools provided: the model cannot make further tool calls
|
|
138
|
+
)
|
|
139
|
+
return response.output_text
|
|
140
|
+
|
|
93
141
|
def _run_tool_loop(
|
|
94
142
|
self,
|
|
95
143
|
messages: list[dict[str, Any]],
|
|
@@ -101,8 +149,12 @@ class OpenAI_Tool_LLM(OpenAI_LLM):
|
|
|
101
149
|
"""Run the agentic tool-call loop for a single turn.
|
|
102
150
|
|
|
103
151
|
Calls the OpenAI API in a loop, executing any tool calls the model
|
|
104
|
-
requests, until the model produces a final text response or
|
|
105
|
-
|
|
152
|
+
requests, until the model produces a final text response or a limit is
|
|
153
|
+
reached. Two limits apply:
|
|
154
|
+
- max_tool_iterations: rounds allowed within this single call.
|
|
155
|
+
- max_tool_calls: cumulative total across all calls on this instance.
|
|
156
|
+
When either limit is hit, _force_final_answer() is called, which tells
|
|
157
|
+
the model to answer immediately without making any further tool calls.
|
|
106
158
|
|
|
107
159
|
Returns the final text response.
|
|
108
160
|
"""
|
|
@@ -118,7 +170,7 @@ class OpenAI_Tool_LLM(OpenAI_LLM):
|
|
|
118
170
|
# and the richer tool-call dicts without fighting the type checker.
|
|
119
171
|
current_input: list[Any] = list(messages)
|
|
120
172
|
|
|
121
|
-
for _ in range(
|
|
173
|
+
for _ in range(self._max_tool_iterations):
|
|
122
174
|
response = self._client.responses.create(
|
|
123
175
|
input=cast(list[ResponseInputItemParam], current_input),
|
|
124
176
|
model=model,
|
|
@@ -137,6 +189,18 @@ class OpenAI_Tool_LLM(OpenAI_LLM):
|
|
|
137
189
|
if not function_calls:
|
|
138
190
|
return response.output_text
|
|
139
191
|
|
|
192
|
+
# check the overall cumulative limit before processing these calls.
|
|
193
|
+
# if adding them would exceed the limit, force a final answer now
|
|
194
|
+
# without executing any of the pending tool calls.
|
|
195
|
+
if self._tool_calls + len(function_calls) > self._max_tool_calls:
|
|
196
|
+
return self._force_final_answer(
|
|
197
|
+
current_input=current_input,
|
|
198
|
+
model=model,
|
|
199
|
+
temperature=temperature,
|
|
200
|
+
top_p=top_p,
|
|
201
|
+
max_tokens=max_tokens,
|
|
202
|
+
)
|
|
203
|
+
|
|
140
204
|
# increment the cumulative counter; parallel calls count individually
|
|
141
205
|
self._tool_calls += len(function_calls)
|
|
142
206
|
|
|
@@ -172,8 +236,14 @@ class OpenAI_Tool_LLM(OpenAI_LLM):
|
|
|
172
236
|
|
|
173
237
|
# loop continues: enriched input is sent back to the model
|
|
174
238
|
|
|
175
|
-
#
|
|
176
|
-
return
|
|
239
|
+
# max_tool_iterations exhausted — force the model to answer now
|
|
240
|
+
return self._force_final_answer(
|
|
241
|
+
current_input=current_input,
|
|
242
|
+
model=model,
|
|
243
|
+
temperature=temperature,
|
|
244
|
+
top_p=top_p,
|
|
245
|
+
max_tokens=max_tokens,
|
|
246
|
+
)
|
|
177
247
|
|
|
178
248
|
def generate(
|
|
179
249
|
self,
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_codegen_research.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llm-codegen-research
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.14
|
|
4
4
|
Summary: Useful classes and methods for researching code-generation by LLMs.
|
|
5
5
|
Author-email: Lukas Twist <itsluketwist@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/itsluketwist/llm-codegen-research
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/__init__.py
RENAMED
|
File without changes
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/code_data.py
RENAMED
|
File without changes
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/javascript.py
RENAMED
|
File without changes
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/python.py
RENAMED
|
File without changes
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/analyse/languages/rust.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{llm_codegen_research-2.13 → llm_codegen_research-2.14}/src/llm_cgr/llm/clients/anthropic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|