prompt-caller 0.1.4__py3-none-any.whl → 0.2.1__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.
- prompt_caller/prompt_caller.py +71 -65
- {prompt_caller-0.1.4.dist-info → prompt_caller-0.2.1.dist-info}/METADATA +7 -6
- prompt_caller-0.2.1.dist-info/RECORD +8 -0
- prompt_caller-0.1.4.dist-info/RECORD +0 -8
- {prompt_caller-0.1.4.dist-info → prompt_caller-0.2.1.dist-info}/LICENSE +0 -0
- {prompt_caller-0.1.4.dist-info → prompt_caller-0.2.1.dist-info}/WHEEL +0 -0
- {prompt_caller-0.1.4.dist-info → prompt_caller-0.2.1.dist-info}/top_level.txt +0 -0
prompt_caller/prompt_caller.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
+
import ast
|
|
3
4
|
|
|
4
5
|
import requests
|
|
5
6
|
import yaml
|
|
6
7
|
from dotenv import load_dotenv
|
|
7
8
|
from jinja2 import Template
|
|
9
|
+
from langgraph.types import Command
|
|
8
10
|
from langchain_core.tools import tool
|
|
9
11
|
from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage
|
|
12
|
+
from langchain.agents import create_agent
|
|
13
|
+
from langchain.agents.middleware import wrap_tool_call
|
|
10
14
|
from langchain_openai import ChatOpenAI
|
|
11
15
|
from langchain_google_genai import ChatGoogleGenerativeAI
|
|
12
16
|
from PIL import Image
|
|
@@ -157,86 +161,88 @@ class PromptCaller:
|
|
|
157
161
|
|
|
158
162
|
return response
|
|
159
163
|
|
|
164
|
+
def _create_media_middleware(self):
|
|
165
|
+
"""Middleware to handle tool responses that contain media content (images, PDFs)."""
|
|
166
|
+
|
|
167
|
+
@wrap_tool_call
|
|
168
|
+
def handle_media_response(request, handler):
|
|
169
|
+
result = handler(request)
|
|
170
|
+
|
|
171
|
+
if hasattr(result, "content"):
|
|
172
|
+
content = result.content
|
|
173
|
+
|
|
174
|
+
if isinstance(content, str) and content.startswith("["):
|
|
175
|
+
try:
|
|
176
|
+
content = ast.literal_eval(content)
|
|
177
|
+
except (ValueError, SyntaxError):
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
# Check if content is media (image or PDF)
|
|
181
|
+
if (
|
|
182
|
+
isinstance(content, list)
|
|
183
|
+
and content
|
|
184
|
+
and isinstance(content[0], dict)
|
|
185
|
+
):
|
|
186
|
+
is_media = (
|
|
187
|
+
"image_url" in content[0] # Image
|
|
188
|
+
or ("input_file" == content[0].get("type", "").strip()) # PDF
|
|
189
|
+
)
|
|
190
|
+
if is_media:
|
|
191
|
+
return Command(
|
|
192
|
+
update={"messages": [result, HumanMessage(content=content)]}
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return result
|
|
196
|
+
|
|
197
|
+
return handle_media_response
|
|
198
|
+
|
|
160
199
|
def agent(
|
|
161
200
|
self, promptName, context=None, tools=None, output=None, allowed_steps=10
|
|
162
201
|
):
|
|
163
202
|
configuration, messages = self.loadPrompt(promptName, context)
|
|
164
203
|
|
|
204
|
+
# Handle structured output from config
|
|
165
205
|
dynamicOutput = None
|
|
166
|
-
|
|
167
206
|
if output is None and "output" in configuration:
|
|
168
|
-
dynamicOutput = configuration.
|
|
169
|
-
configuration.pop("output")
|
|
170
|
-
|
|
171
|
-
for message in messages:
|
|
172
|
-
if isinstance(message, SystemMessage):
|
|
173
|
-
message.content += "\n\nYou have to use the tool `dynamicmodel` when providing your final answer. If you don't, you have failed the task."
|
|
174
|
-
break
|
|
207
|
+
dynamicOutput = configuration.pop("output")
|
|
175
208
|
|
|
176
209
|
chat = self._createChat(configuration)
|
|
177
210
|
|
|
178
|
-
#
|
|
211
|
+
# Prepare tools
|
|
179
212
|
if tools is None:
|
|
180
213
|
tools = []
|
|
181
|
-
|
|
182
|
-
# Transform functions in tools
|
|
183
214
|
tools = [tool(t) for t in tools]
|
|
184
215
|
|
|
185
|
-
|
|
186
|
-
|
|
216
|
+
# Handle response format (structured output)
|
|
217
|
+
response_format = None
|
|
187
218
|
if output:
|
|
188
|
-
|
|
189
|
-
tools_dict[output.__name__.lower()] = output
|
|
219
|
+
response_format = output
|
|
190
220
|
elif dynamicOutput:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return dynamicModel.model_validate(tool_call["args"])
|
|
211
|
-
|
|
212
|
-
if output and tool_name == output.__name__.lower():
|
|
213
|
-
return output.model_validate(tool_call["args"])
|
|
214
|
-
|
|
215
|
-
selected_tool = tools_dict.get(tool_name)
|
|
216
|
-
if not selected_tool:
|
|
217
|
-
raise ValueError(f"Unknown tool: {tool_name}")
|
|
218
|
-
|
|
219
|
-
# Invoke the selected tool with provided arguments
|
|
220
|
-
tool_response = selected_tool.invoke(tool_call)
|
|
221
|
-
messages.append(tool_response)
|
|
222
|
-
|
|
223
|
-
# If the latest message is a ToolMessage, re-invoke the LLM
|
|
224
|
-
if isinstance(messages[-1], ToolMessage):
|
|
225
|
-
response = chat.invoke(messages)
|
|
226
|
-
messages.append(response)
|
|
227
|
-
else:
|
|
228
|
-
break
|
|
229
|
-
|
|
230
|
-
steps += 1
|
|
231
|
-
|
|
232
|
-
# Final LLM call if the last message is still a ToolMessage
|
|
233
|
-
if isinstance(messages[-1], ToolMessage):
|
|
234
|
-
response = chat.invoke(messages)
|
|
235
|
-
messages.append(response)
|
|
221
|
+
response_format = self.createPydanticModel(dynamicOutput)
|
|
222
|
+
|
|
223
|
+
# Extract system message for create_agent
|
|
224
|
+
system_prompt = None
|
|
225
|
+
user_messages = []
|
|
226
|
+
for msg in messages:
|
|
227
|
+
if isinstance(msg, SystemMessage):
|
|
228
|
+
system_prompt = msg.content
|
|
229
|
+
else:
|
|
230
|
+
user_messages.append(msg)
|
|
231
|
+
|
|
232
|
+
# Create and invoke agent
|
|
233
|
+
agent_graph = create_agent(
|
|
234
|
+
model=chat,
|
|
235
|
+
tools=tools,
|
|
236
|
+
system_prompt=system_prompt,
|
|
237
|
+
response_format=response_format,
|
|
238
|
+
middleware=[self._create_media_middleware()],
|
|
239
|
+
)
|
|
236
240
|
|
|
237
|
-
|
|
241
|
+
result = agent_graph.invoke(
|
|
242
|
+
{"messages": user_messages}, config={"recursion_limit": allowed_steps}
|
|
243
|
+
)
|
|
238
244
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
245
|
+
# Return structured output or last message
|
|
246
|
+
if response_format and result.get("structured_response"):
|
|
247
|
+
return result["structured_response"]
|
|
248
|
+
return result["messages"][-1]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: prompt_caller
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: This package is responsible for calling prompts in a specific format. It uses LangChain and OpenAI API
|
|
5
5
|
Home-page: https://github.com/ThiNepo/prompt-caller
|
|
6
6
|
Author: Thiago Nepomuceno
|
|
@@ -11,12 +11,13 @@ Classifier: Operating System :: OS Independent
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Requires-Dist: pyyaml>=6.0.2
|
|
14
|
-
Requires-Dist: python-dotenv>=1.
|
|
14
|
+
Requires-Dist: python-dotenv>=1.2.1
|
|
15
15
|
Requires-Dist: Jinja2>=3.1.4
|
|
16
|
-
Requires-Dist: langchain
|
|
17
|
-
Requires-Dist: langchain-
|
|
18
|
-
Requires-Dist:
|
|
19
|
-
Requires-Dist:
|
|
16
|
+
Requires-Dist: langchain>=1.2.7
|
|
17
|
+
Requires-Dist: langchain-openai>=1.1.7
|
|
18
|
+
Requires-Dist: langchain-google-genai>=4.2.0
|
|
19
|
+
Requires-Dist: openai>=2.16.0
|
|
20
|
+
Requires-Dist: pillow>=12.1.0
|
|
20
21
|
|
|
21
22
|
# PromptCaller
|
|
22
23
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
prompt_caller/__init__.py,sha256=4EGdeAJ_Ig7A-b-e17-nYbiXjckT7uL3to5lchMsoW4,41
|
|
2
|
+
prompt_caller/__main__.py,sha256=dJ0dYtVmnhZuoV79R6YiAIta1ZkUKb-TEX4VEuYbgk0,139
|
|
3
|
+
prompt_caller/prompt_caller.py,sha256=U2K_qMMuTBP94cjdac7gPhac8Y6DGOSClfIBFuwpztg,8356
|
|
4
|
+
prompt_caller-0.2.1.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
5
|
+
prompt_caller-0.2.1.dist-info/METADATA,sha256=b7cSmJA138gThOs1rB298gyS_yFPmbA4OlDfAAEXqL0,4988
|
|
6
|
+
prompt_caller-0.2.1.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
|
7
|
+
prompt_caller-0.2.1.dist-info/top_level.txt,sha256=iihiDRq-0VrKB8IKjxf7Lrtv-fLMq4tvgM4fH3x0I94,14
|
|
8
|
+
prompt_caller-0.2.1.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
prompt_caller/__init__.py,sha256=4EGdeAJ_Ig7A-b-e17-nYbiXjckT7uL3to5lchMsoW4,41
|
|
2
|
-
prompt_caller/__main__.py,sha256=dJ0dYtVmnhZuoV79R6YiAIta1ZkUKb-TEX4VEuYbgk0,139
|
|
3
|
-
prompt_caller/prompt_caller.py,sha256=0Rqfzp7hUgPH10auxEwJMoaASOSZNlTyDvS8Hd6X0Yk,8333
|
|
4
|
-
prompt_caller-0.1.4.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
5
|
-
prompt_caller-0.1.4.dist-info/METADATA,sha256=0x0EKp50KvL-dYuc9n8TEvouL53jD_V1fMw2bSKGPEY,4955
|
|
6
|
-
prompt_caller-0.1.4.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
|
7
|
-
prompt_caller-0.1.4.dist-info/top_level.txt,sha256=iihiDRq-0VrKB8IKjxf7Lrtv-fLMq4tvgM4fH3x0I94,14
|
|
8
|
-
prompt_caller-0.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|