lollms-client 0.17.2__py3-none-any.whl → 0.19.0__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 lollms-client might be problematic. Click here for more details.

@@ -0,0 +1,107 @@
1
+ from typing import Dict, Any, List
2
+
3
+ # --- Package Management ---
4
+ _duckduckgo_search_installed = False
5
+ _installation_error_message = ""
6
+ try:
7
+ import pipmaster as pm
8
+ pm.ensure_packages(["duckduckgo_search"])
9
+ from duckduckgo_search import DDGS
10
+ _duckduckgo_search_installed = True
11
+ except Exception as e:
12
+ _installation_error_message = str(e)
13
+ DDGS = None # Ensure DDGS is None if import fails
14
+ # --- End Package Management ---
15
+
16
+ def execute(params: Dict[str, Any]) -> Dict[str, Any]:
17
+ """
18
+ Performs an internet search using DuckDuckGo.
19
+ """
20
+ if not _duckduckgo_search_installed:
21
+ return {
22
+ "search_results": [],
23
+ "error": f"Required library 'duckduckgo_search' is not installed or import failed: {_installation_error_message}"
24
+ }
25
+
26
+ query = params.get("query")
27
+ num_results = params.get("num_results", 5)
28
+
29
+ if not query:
30
+ return {"search_results": [], "error": "'query' parameter is required."}
31
+ if not isinstance(num_results, int) or num_results <= 0:
32
+ num_results = 5 # Default to 5 if invalid
33
+
34
+ try:
35
+ search_results_formatted: List[Dict[str, str]] = []
36
+ # DDGS().text returns a generator, max_results limits it.
37
+ # Note: The DDGS library might sometimes return fewer results than max_results.
38
+ with DDGS() as ddgs:
39
+ results = ddgs.text(keywords=query, max_results=num_results)
40
+ if results:
41
+ for r in results:
42
+ search_results_formatted.append({
43
+ "title": r.get("title", "N/A"),
44
+ "link": r.get("href", "#"),
45
+ "snippet": r.get("body", "N/A")
46
+ })
47
+
48
+ if not search_results_formatted and results is None: # Check if ddgs.text itself returned None
49
+ return {"search_results": [], "error": "Search returned no results or failed to connect."}
50
+
51
+
52
+ return {"search_results": search_results_formatted, "error": None}
53
+
54
+ except Exception as e:
55
+ # Log the exception for server-side debugging if possible
56
+ # For now, just return it in the error field.
57
+ print(f"Error during internet search: {str(e)}") # Basic logging
58
+ # from ascii_colors import trace_exception (if you want to import it here)
59
+ # trace_exception(e)
60
+ return {"search_results": [], "error": f"An unexpected error occurred during search: {str(e)}"}
61
+
62
+ if __name__ == '__main__':
63
+ import json
64
+ print("--- Internet Search Tool Test ---")
65
+
66
+ if not _duckduckgo_search_installed:
67
+ print(f"Cannot run test: duckduckgo_search not installed. Error: {_installation_error_message}")
68
+ else:
69
+ # Test 1: Simple search
70
+ params1 = {"query": "What is the capital of France?", "num_results": 3}
71
+ result1 = execute(params1)
72
+ print(f"\nTest 1 Result (Query: '{params1['query']}'):\n{json.dumps(result1, indent=2)}")
73
+ if result1.get("search_results"):
74
+ assert len(result1["search_results"]) <= 3
75
+ assert "error" not in result1 or result1["error"] is None
76
+ else:
77
+ print(f"Warning: Test 1 might have failed to retrieve results. Error: {result1.get('error')}")
78
+
79
+
80
+ # Test 2: Search with more results
81
+ params2 = {"query": "Latest AI breakthroughs", "num_results": 6}
82
+ result2 = execute(params2)
83
+ print(f"\nTest 2 Result (Query: '{params2['query']}'):\n{json.dumps(result2, indent=2)}")
84
+ if result2.get("search_results"):
85
+ assert len(result2["search_results"]) <= 6
86
+ else:
87
+ print(f"Warning: Test 2 might have failed to retrieve results. Error: {result2.get('error')}")
88
+
89
+
90
+ # Test 3: No query
91
+ params3 = {}
92
+ result3 = execute(params3)
93
+ print(f"\nTest 3 Result (No query):\n{json.dumps(result3, indent=2)}")
94
+ assert result3["error"] is not None
95
+ assert "query' parameter is required" in result3["error"]
96
+
97
+ # Test 4: Invalid num_results
98
+ params4 = {"query": "python programming", "num_results": -1}
99
+ result4 = execute(params4) # Should default to 5
100
+ print(f"\nTest 4 Result (Invalid num_results):\n{json.dumps(result4, indent=2)}")
101
+ if result4.get("search_results"):
102
+ assert len(result4["search_results"]) <= 5
103
+ else:
104
+ print(f"Warning: Test 4 might have failed to retrieve results. Error: {result4.get('error')}")
105
+
106
+
107
+ print("\n--- Tests Finished ---")
@@ -0,0 +1,141 @@
1
+ import subprocess
2
+ import tempfile
3
+ from pathlib import Path
4
+ from typing import Dict, Any
5
+ import sys
6
+ import json
7
+ import pipmaster as pm
8
+ pm.ensure_packages(["RestrictedPython"])
9
+
10
+ import RestrictedPython
11
+ from RestrictedPython import compile_restricted, safe_globals
12
+ from RestrictedPython.PrintCollector import PrintCollector
13
+
14
+
15
+ def execute(params: Dict[str, Any]) -> Dict[str, Any]:
16
+ """
17
+ Executes a snippet of Python code in a restricted environment.
18
+ """
19
+ code = params.get("code")
20
+ timeout_seconds = params.get("timeout_seconds", 10)
21
+
22
+ if not code:
23
+ return {
24
+ "stdout": "",
25
+ "stderr": "Error: 'code' parameter is required.",
26
+ "returned_value": None,
27
+ "execution_status": "error"
28
+ }
29
+
30
+ # For this local tool, we'll use RestrictedPython for a degree of safety.
31
+ # A more robust solution for untrusted code would involve containers (e.g., Docker)
32
+ # or a more heavily sandboxed environment. RestrictedPython is not foolproof.
33
+
34
+ restricted_globals = dict(safe_globals) # type: ignore
35
+ restricted_globals['_print_'] = PrintCollector # Capture print statements
36
+ restricted_globals['_getattr_'] = RestrictedPython.Guards.safer_getattr # Allow safer attribute access
37
+ # Add more globals if needed, e.g., math module, but be cautious.
38
+ # restricted_globals['math'] = math
39
+
40
+ stdout_capture = ""
41
+ stderr_capture = ""
42
+ returned_value_str = None
43
+ status = "error" # Default to error
44
+
45
+ try:
46
+ # Compile the code in restricted mode
47
+ # Adding "<string>" as the filename for tracebacks
48
+ byte_code = compile_restricted(code, filename='<inline_script>', mode='exec')
49
+
50
+ # Prepare a dictionary for local variables, including the print collector
51
+ local_vars = {}
52
+
53
+ # Execute the compiled code
54
+ # Note: RestrictedPython's exec doesn't directly support timeout.
55
+ # A more complex setup with threading or multiprocessing would be needed for true timeout.
56
+ # For simplicity, this example doesn't implement a hard timeout for RestrictedPython's exec.
57
+ # The timeout_seconds param is more of a hint for now or for alternative execution methods.
58
+
59
+ exec(byte_code, restricted_globals, local_vars)
60
+
61
+ stdout_capture = restricted_globals['_print']() # Get captured prints
62
+ # RestrictedPython itself doesn't easily separate stdout/stderr from exec.
63
+ # Errors during compilation or guarded execution will raise exceptions.
64
+
65
+ # Try to get a returned value if the script used 'return' (not typical for 'exec' mode)
66
+ # or if a specific variable was set to indicate a return.
67
+ # For this example, we won't try to capture implicit returns from 'exec'.
68
+ # If the executed code sets a variable like `result = ...`, it would be in `local_vars`.
69
+ # We'll consider `returned_value` as None for simplicity with 'exec'.
70
+
71
+ status = "success"
72
+
73
+ except SyntaxError as se:
74
+ stderr_capture = f"SyntaxError: {se}"
75
+ status = "error"
76
+ except RestrictedPython.Guards. इलाकोंOnlyĐiPythonGuardViolation as rpe: # Common RestrictedPython error
77
+ stderr_capture = f"RestrictedPythonError: {rpe}"
78
+ status = "error"
79
+ except NameError as ne: # Undeclared variable
80
+ stderr_capture = f"NameError: {ne}"
81
+ status = "error"
82
+ except TypeError as te:
83
+ stderr_capture = f"TypeError: {te}"
84
+ status = "error"
85
+ except Exception as e:
86
+ stderr_capture = f"Execution Error: {type(e).__name__}: {e}"
87
+ status = "error"
88
+ trace_exception(e) # For more detailed logging if needed
89
+
90
+ return {
91
+ "stdout": stdout_capture,
92
+ "stderr": stderr_capture,
93
+ "returned_value": returned_value_str, # Typically None with exec
94
+ "execution_status": status
95
+ }
96
+
97
+
98
+ if __name__ == '__main__':
99
+ # Example Tests
100
+ print("--- Python Interpreter Tool Test ---")
101
+
102
+ # Test 1: Simple print
103
+ params1 = {"code": "print('Hello from restricted Python!')\nx = 10 + 5\nprint(f'Result is {x}')"}
104
+ result1 = execute(params1)
105
+ print(f"\nTest 1 Result:\n{json.dumps(result1, indent=2)}")
106
+ assert result1["execution_status"] == "success"
107
+ assert "Hello from restricted Python!" in result1["stdout"]
108
+ assert "Result is 15" in result1["stdout"]
109
+
110
+ # Test 2: Code with an error (e.g., trying to access restricted features)
111
+ params2 = {"code": "import os\nprint(os.getcwd())"} # os is usually restricted
112
+ result2 = execute(params2)
113
+ print(f"\nTest 2 Result (expected error):\n{json.dumps(result2, indent=2)}")
114
+ assert result2["execution_status"] == "error"
115
+ assert "RestrictedPythonError" in result2["stderr"] or "NameError" in result2["stderr"] # Depending on how os import fails
116
+
117
+ # Test 3: Syntax error
118
+ params3 = {"code": "print('Hello without closing quote"}
119
+ result3 = execute(params3)
120
+ print(f"\nTest 3 Result (syntax error):\n{json.dumps(result3, indent=2)}")
121
+ assert result3["execution_status"] == "error"
122
+ assert "SyntaxError" in result3["stderr"]
123
+
124
+ # Test 4: No code
125
+ params4 = {"code": ""}
126
+ result4 = execute(params4) # Should succeed with empty output or be handled if empty code is invalid.
127
+ # Current RestrictedPython might raise error on empty.
128
+ print(f"\nTest 4 Result (empty code):\n{json.dumps(result4, indent=2)}")
129
+ # Depending on compile_restricted behavior for empty string, this might be success or error.
130
+ # It seems compile_restricted can handle empty strings.
131
+ assert result4["execution_status"] == "success"
132
+ assert result4["stdout"] == ""
133
+
134
+ # Test 5: Attempting a disallowed attribute
135
+ params5 = {"code": "x = ().__class__"} # Example of trying to access something disallowed
136
+ result5 = execute(params5)
137
+ print(f"\nTest 5 Result (disallowed attribute):\n{json.dumps(result5, indent=2)}")
138
+ assert result5["execution_status"] == "error"
139
+ assert "RestrictedPythonError" in result5["stderr"]
140
+
141
+ print("\n--- Tests Finished ---")
@@ -152,7 +152,8 @@ class DalleTTIBinding_Impl(LollmsTTIBinding):
152
152
  # Format size string and validate against the active model for this generation
153
153
  size_str = f"{width}x{height}"
154
154
  if size_str not in model_props["sizes"]:
155
- raise ValueError(f"Unsupported size '{size_str}' for model '{active_model_name}'. Supported sizes: {model_props['sizes']}. Adjust width/height for this model.")
155
+ ASCIIColors.warning(f"Unsupported size '{size_str}' for model '{active_model_name}'. Supported sizes: {model_props['sizes']}. Adjust width/height for this model.")
156
+ size_str = model_props["sizes"][0]
156
157
 
157
158
  # Handle prompt and negative prompt based on the active model
158
159
  final_prompt = prompt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lollms_client
3
- Version: 0.17.2
3
+ Version: 0.19.0
4
4
  Summary: A client library for LoLLMs generate endpoint
5
5
  Author-email: ParisNeo <parisneoai@gmail.com>
6
6
  License: Apache Software License
@@ -1,3 +1,5 @@
1
+ examples/function_calling_with_local_custom_mcp.py,sha256=g6wOFRB8-p9Cv7hKmQaGzPvtMX3H77gas01QVNEOduM,12407
2
+ examples/local_mcp.py,sha256=w40dgayvHYe01yvekEE0LjcbkpwKjWwJ-9v4_wGYsUk,9113
1
3
  examples/simple_text_gen_test.py,sha256=RoX9ZKJjGMujeep60wh5WT_GoBn0O9YKJY6WOy-ZmOc,8710
2
4
  examples/simple_text_gen_with_image_test.py,sha256=rR1O5Prcb52UHtJ3c6bv7VuTd1cvbkr5aNZU-v-Rs3Y,9263
3
5
  examples/text_2_audio.py,sha256=MfL4AH_NNwl6m0I0ywl4BXRZJ0b9Y_9fRqDIe6O-Sbw,3523
@@ -9,23 +11,21 @@ examples/text_gen_system_prompt.py,sha256=jRQeGe1IVu_zRHX09CFiDYi7WrK9Zd5FlMqC_g
9
11
  examples/article_summary/article_summary.py,sha256=CR8mCBNcZEVCR-q34uOmrJyMlG-xk4HkMbsV-TOZEnk,1978
10
12
  examples/deep_analyze/deep_analyse.py,sha256=fZNmDrfEAuxEAfdbjAgJYIh1k6wbiuZ4RvwHRvtyUs8,971
11
13
  examples/deep_analyze/deep_analyze_multiple_files.py,sha256=fOryShA33P4IFxcxUDe-nJ2kW0v9w9yW8KsToS3ETl8,1032
12
- examples/function_call/functions_call_with images.py,sha256=jrNtTF7lAzad25Ob0Yv4pwLs12HSzDamKKR9ORkNWjc,1888
13
14
  examples/generate_and_speak/generate_and_speak.py,sha256=RAlvRwtEKXCh894l9M3iQbADe8CvF5N442jtRurK02I,13908
14
15
  examples/generate_game_sfx/generate_game_fx.py,sha256=MgLNGi4hGBRoyr4bqYuCUdCSqd-ldDVfF0VSDUjgzsg,10467
15
16
  examples/personality_test/chat_test.py,sha256=o2jlpoddFc-T592iqAiA29xk3x27KsdK5DluqxBwHqw,1417
16
17
  examples/personality_test/chat_with_aristotle.py,sha256=4X_fwubMpd0Eq2rCReS2bgVlUoAqJprjkLXk2Jz6pXU,1774
17
18
  examples/personality_test/tesks_test.py,sha256=7LIiwrEbva9WWZOLi34fsmCBN__RZbPpxoUOKA_AtYk,1924
18
19
  examples/test_local_models/local_chat.py,sha256=slakja2zaHOEAUsn2tn_VmI4kLx6luLBrPqAeaNsix8,456
19
- lollms_client/__init__.py,sha256=D-gKzzHJSNT09aCJipQi6CUfwb4bSCUwZ-jP2VmalwE,823
20
+ lollms_client/__init__.py,sha256=7YwfgI-rPt3hNWyG5_ObEgKMsRGXYBu6QDe97v_Cc0g,910
20
21
  lollms_client/lollms_config.py,sha256=goEseDwDxYJf3WkYJ4IrLXwg3Tfw73CXV2Avg45M_hE,21876
21
- lollms_client/lollms_core.py,sha256=fRHdQ0yWAmMuOLZAzDbdlYfCsx0Rb8rQ-RYl_bKgEHk,80049
22
+ lollms_client/lollms_core.py,sha256=psVTrEtHYhjy9h014rHLotBC4Aj72PvG2OV0UAjLcvw,102496
22
23
  lollms_client/lollms_discussion.py,sha256=9b83m0D894jwpgssWYTQHbVxp1gJoI-J947Ui_dRXII,2073
23
- lollms_client/lollms_functions.py,sha256=p8SFtmEPqvVCsIz2fZ5HxyOHaxjrAo5c12uTzJnb6m8,3594
24
24
  lollms_client/lollms_js_analyzer.py,sha256=01zUvuO2F_lnUe_0NLxe1MF5aHE1hO8RZi48mNPv-aw,8361
25
25
  lollms_client/lollms_llm_binding.py,sha256=bdElz_IBx0zZ-85YTT1fyY_mSoHo46tKIMiHYJlKCkM,9809
26
+ lollms_client/lollms_mcp_binding.py,sha256=0rK9HQCBEGryNc8ApBmtOlhKE1Yfn7X7xIQssXxS2Zc,8933
26
27
  lollms_client/lollms_python_analyzer.py,sha256=7gf1fdYgXCOkPUkBAPNmr6S-66hMH4_KonOMsADASxc,10246
27
28
  lollms_client/lollms_stt_binding.py,sha256=jAUhLouEhh2hmm1bK76ianfw_6B59EHfY3FmLv6DU-g,5111
28
- lollms_client/lollms_tasks.py,sha256=Tgqces03gPTHFJCcPaeN9vBCsil3SSJX7nQAjCQ2-yg,34393
29
29
  lollms_client/lollms_tti_binding.py,sha256=afO0-d-Kqsmh8UHTijTvy6dZAt-XDB6R-IHmdbf-_fs,5928
30
30
  lollms_client/lollms_ttm_binding.py,sha256=FjVVSNXOZXK1qvcKEfxdiX6l2b4XdGOSNnZ0utAsbDg,4167
31
31
  lollms_client/lollms_tts_binding.py,sha256=5cJYECj8PYLJAyB6SEH7_fhHYK3Om-Y3arkygCnZ24o,4342
@@ -42,12 +42,17 @@ lollms_client/llm_bindings/pythonllamacpp/__init__.py,sha256=7dM42TCGKh0eV0njNL1
42
42
  lollms_client/llm_bindings/tensor_rt/__init__.py,sha256=nPaNhGRd-bsG0UlYwcEqjd_UagCMEf5VEbBUW-GWu6A,32203
43
43
  lollms_client/llm_bindings/transformers/__init__.py,sha256=9LkqEC5bp1zHgyeGEcPQ3_uqvEAEf_B4p9DztcBaC5w,37211
44
44
  lollms_client/llm_bindings/vllm/__init__.py,sha256=2NqeeqYWXNq1aNicdcAwN9DaoL4gq96GZ7hsKErfC6c,32187
45
+ lollms_client/mcp_bindings/local_mcp/__init__.py,sha256=FxS-0PULS3TZScPLDbwHlfyW5joWucmMfn6b9ydyeM0,14341
46
+ lollms_client/mcp_bindings/local_mcp/default_tools/file_writer/file_writer.py,sha256=2pkt1JcEKj61lIA5zuW3s6qkdpQN5rKfooo7bnebx24,3061
47
+ lollms_client/mcp_bindings/local_mcp/default_tools/generate_image_from_prompt/generate_image_from_prompt.py,sha256=THtZsMxNnXZiBdkwoBlfbWY2C5hhDdmPtnM-8cSKN6s,9488
48
+ lollms_client/mcp_bindings/local_mcp/default_tools/internet_search/internet_search.py,sha256=PLC31-D04QKTOTb1uuCHnrAlpysQjsk89yIJngK0VGc,4586
49
+ lollms_client/mcp_bindings/local_mcp/default_tools/python_interpreter/python_interpreter.py,sha256=McDCBVoVrMDYgU7EYtyOY7mCk1uEeTea0PSD69QqDsQ,6228
45
50
  lollms_client/stt_bindings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
51
  lollms_client/stt_bindings/lollms/__init__.py,sha256=jBz3285atdPRqQe9ZRrb-AvjqKRB4f8tjLXjma0DLfE,6082
47
52
  lollms_client/stt_bindings/whisper/__init__.py,sha256=vrua7fLwDId9_WiH4y2gXOE0hy3Gr2Ig-z5ScIT2bHI,15447
48
53
  lollms_client/stt_bindings/whispercpp/__init__.py,sha256=B45lOn5rSoHXJSG9duPzBEPBOoNTrDzpCUdOL8KHaDM,21874
49
54
  lollms_client/tti_bindings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
- lollms_client/tti_bindings/dalle/__init__.py,sha256=VuuCWQb6Y3b5-SdU9dMpiKAa2s_4h_B58jE10L8LTak,23577
55
+ lollms_client/tti_bindings/dalle/__init__.py,sha256=V-rODzcwaN9eg0wX8DGOQXXcDtnYYDWYD6t6pFNTo0w,23628
51
56
  lollms_client/tti_bindings/diffusers/__init__.py,sha256=Hcu3F3KU8h6b_T4Dpl98OsQrsUoecd_z7xOVIEyYoDc,37679
52
57
  lollms_client/tti_bindings/gemini/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
58
  lollms_client/tti_bindings/lollms/__init__.py,sha256=GJShFW6Y8MrfM9PXaPrdAp8OUpD6rraSRFt8ZOnrauo,8735
@@ -62,8 +67,8 @@ lollms_client/tts_bindings/piper_tts/__init__.py,sha256=0IEWG4zH3_sOkSb9WbZzkeV5
62
67
  lollms_client/tts_bindings/xtts/__init__.py,sha256=FgcdUH06X6ZR806WQe5ixaYx0QoxtAcOgYo87a2qxYc,18266
63
68
  lollms_client/ttv_bindings/__init__.py,sha256=UZ8o2izQOJLQgtZ1D1cXoNST7rzqW22rL2Vufc7ddRc,3141
64
69
  lollms_client/ttv_bindings/lollms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- lollms_client-0.17.2.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
66
- lollms_client-0.17.2.dist-info/METADATA,sha256=tAj-msqkBvc8uFcVXq0a-RLD8lP70hAkkrsEUBRLsb0,9798
67
- lollms_client-0.17.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
- lollms_client-0.17.2.dist-info/top_level.txt,sha256=NI_W8S4OYZvJjb0QWMZMSIpOrYzpqwPGYaklhyWKH2w,23
69
- lollms_client-0.17.2.dist-info/RECORD,,
70
+ lollms_client-0.19.0.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
71
+ lollms_client-0.19.0.dist-info/METADATA,sha256=omhefcFH2TBEIAs0dRspAQN3mBHpJqga8Q_Qhy14bcE,9798
72
+ lollms_client-0.19.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
73
+ lollms_client-0.19.0.dist-info/top_level.txt,sha256=NI_W8S4OYZvJjb0QWMZMSIpOrYzpqwPGYaklhyWKH2w,23
74
+ lollms_client-0.19.0.dist-info/RECORD,,
@@ -1,52 +0,0 @@
1
- import cv2
2
- from lollms_client import LollmsClient, LollmsTTS, TasksLibrary, FunctionCalling_Library
3
- import random
4
-
5
- # Initialize the LollmsClient instance
6
- lc = LollmsClient()
7
- tl = TasksLibrary(lc)
8
- tts = LollmsTTS(lc)
9
- fcl = FunctionCalling_Library(tl)
10
- voices = tts.get_voices()
11
- if voices:
12
- # Pick a voice randomly
13
- random_voice = random.choice(voices)
14
- print(f"Selected voice: {random_voice}")
15
-
16
- # File path to save the captured image
17
- file_path = "captured_image.jpg"
18
- images = []
19
- # Capture image from webcam and save it to a file
20
- def capture_image():
21
- cap = cv2.VideoCapture(0)
22
- if not cap.isOpened():
23
- raise Exception("Could not open webcam")
24
-
25
- ret, frame = cap.read()
26
- if not ret:
27
- raise Exception("Failed to capture image")
28
- images.clear()
29
- images.append(file_path)
30
- cv2.imwrite(file_path, frame)
31
- cap.release()
32
- return "Image captured successfully"
33
-
34
-
35
- fcl.register_function("capture_image",capture_image,"Captures an image from the user webcam",[])
36
-
37
-
38
-
39
- # Function to handle streaming callback
40
- def cb(chunk, type):
41
- print(chunk, end="", flush=True)
42
-
43
- # Generate text with image
44
- response, function_calls = fcl.generate_with_functions_and_images(prompt="user: take a look at me then tell ma how i look.\nassistant: ", images=images, stream=False, temperature=0.5, streaming_callback=cb)
45
- print(f"response: {response}")
46
- if len(function_calls)>0:
47
- results = fcl.execute_function_calls(function_calls)
48
- result = "\n".join(results)
49
- prompt="user: take a look at me then tell ma how i look.\nassistant: "+response + f"\nfunction execution result: {result}\nassistant: "
50
- response, function_calls = fcl.generate_with_functions_and_images(prompt, images=images, stream=False, temperature=0.5, streaming_callback=cb)
51
- print(f"response: {response}")
52
- tts.text2Audio(response, random_voice)
@@ -1,72 +0,0 @@
1
- from functools import partial
2
- from lollms_client.lollms_tasks import TasksLibrary
3
- from typing import Dict, Any, List
4
-
5
- class FunctionCalling_Library:
6
- def __init__(self, tasks_library:TasksLibrary):
7
- self.tl = tasks_library
8
- self.function_definitions = []
9
-
10
- def register_function(self, function_name, function_callable, function_description, function_parameters):
11
- self.function_definitions.append({
12
- "function_name": function_name,
13
- "function": function_callable,
14
- "function_description": function_description,
15
- "function_parameters": function_parameters
16
- })
17
-
18
- def unregister_function(self, function_name):
19
- self.function_definitions = [func for func in self.function_definitions if func["function_name"] != function_name]
20
-
21
-
22
-
23
- def execute_function_calls(self, function_calls: List[Dict[str, Any]]) -> List[Any]:
24
- """
25
- Executes the function calls with the parameters extracted from the generated text,
26
- using the original functions list to find the right function to execute.
27
-
28
- Args:
29
- function_calls (List[Dict[str, Any]]): A list of dictionaries representing the function calls.
30
- function_definitions (List[Dict[str, Any]]): The original list of functions with their descriptions and callable objects.
31
-
32
- Returns:
33
- List[Any]: A list of results from executing the function calls.
34
- """
35
- results = []
36
- # Convert function_definitions to a dict for easier lookup
37
- functions_dict = {func['function_name']: func['function'] for func in self.function_definitions}
38
-
39
- for call in function_calls:
40
- function_name = call.get("function_name")
41
- parameters = call.get("function_parameters", [])
42
- function = functions_dict.get(function_name)
43
-
44
- if function:
45
- try:
46
- # Assuming parameters is a dictionary that maps directly to the function's arguments.
47
- if type(parameters)==list:
48
- result = function(*parameters)
49
- elif type(parameters)==dict:
50
- result = function(**parameters)
51
- results.append(result)
52
- except TypeError as e:
53
- # Handle cases where the function call fails due to incorrect parameters, etc.
54
- results.append(f"Error calling {function_name}: {e}")
55
- else:
56
- results.append(f"Function {function_name} not found.")
57
-
58
- return results
59
-
60
- def generate_with_functions(self, prompt, stream=False, temperature=0.5, streaming_callback=None):
61
- # Assuming generate_with_function_calls is a method from TasksLibrary
62
- ai_response, function_calls = self.tl.generate_with_function_calls(prompt, self.function_definitions, callback=streaming_callback)
63
- return ai_response, function_calls
64
-
65
- def generate_with_functions_and_images(self, prompt, images=[], stream=False, temperature=0.5, streaming_callback=None):
66
- # Assuming generate_with_function_calls_and_images is a method from TasksLibrary
67
- if len(images) > 0:
68
- ai_response, function_calls = self.tl.generate_with_function_calls_and_images(prompt, images, self.function_definitions, callback=streaming_callback)
69
- else:
70
- ai_response, function_calls = self.tl.generate_with_function_calls(prompt, self.function_definitions)
71
-
72
- return ai_response, function_calls