Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VERSION 1.0.0b1 #147

Merged
merged 59 commits into from
Oct 28, 2024
Merged

VERSION 1.0.0b1 #147

merged 59 commits into from
Oct 28, 2024

Conversation

diogoncalves
Copy link
Collaborator

@diogoncalves diogoncalves commented Oct 16, 2024

LLMstudio Version 1.0.0b1

What was done in this PR:

  • new libraries: llmstudio-core, llmstudio-tracker, llmstudio-proxy, llmstudio (former monolith)
  • Modularization and Refactoring: Shifted the structure towards modularization to enhance maintainability and scalability. Significant changes were made in the core components to make them more modular, including separating server components and organizing imports.
  • LLM Provider Updates: Implemented changes in the LLM provider instantiation. The provider now requires additional parameters such as api_key and accepts a structured chat_request. This restructuring also includes making the proxy and tracking optional for more flexible usage.
  • Feature Enhancements:
    • Added asynchronous chat support, both with and without streaming, and implemented synchronous methods.
    • Introduced session_id tracking for chat sessions and logging support for better traceability.
    • Incorporated dynamic API versioning and the ability to handle multiple API providers, including OpenAI, Azure, and VertexAI.
    • Added support for LangChain agents and tool calling with parallel execution.
    • Adapted VertexAI integration for both regular and tool-calling functions.
    • Provided support for legacy UTC compatibility to address compatibility with older Python versions.
  • Automated Testing and Documentation:
    • Enhanced test automation for development processes, including adding tests for modularized components.
    • Updated the documentation, added docstrings to LLM classes, and provided a tutorial on using langgraph.
  • Formatting and Configuration:
    • Applied consistent formatting, added isort and flake8 configurations, and updated pre-commit hooks.
    • Updated config.yaml for easier configuration management and enhanced initialization for Azure-based clients.

How it was tested:

  • Conducted automated tests across development environments to verify the correctness of modularized components and new functionality.
  • Validated the functionality of asynchronous and synchronous chat capabilities with various LLM providers, including OpenAI, Azure, and VertexAI.
  • Tested new session_id integration for accuracy in tracking sessions and seamless functionality with logging tools.
  • Verified compatibility across Python versions, particularly with UTC handling in legacy versions.
  • Reviewed server component separation and ensured compatibility with modular server deployments.

Additional notes:

  • Any breaking changes?
    Yes, breaking changes were introduced in the LLM provider instantiation. The new instantiation now requires specifying parameters in the following format:

    llm = LLM(provider=provider, api_key=api_key, **kwargs)
    chat_request = {
        "chat_input": "Hello, my name is Json",
        "model": model,
        "is_stream": False,
        "retries": 0,
        "parameters": {
            "temperature": 0,
            "max_tokens": 100,
            "response_format": {"type": "json_object"},
            "functions": None,
        }
    }
    llm.achat(**chat_request)
  • Any new dependencies added?
    New dependencies are introduced to support modularization, API versioning, and enhanced testing, though specific package details should be checked in pyproject.toml.

  • Any performance improvements?
    Optimized API calls with parallel execution for tool calls, streamlined server components, and minimized function calls within the LLM provider, which should contribute to overall performance improvements.

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
if default_port is not None:
s.bind(("", default_port))

Check warning

Code scanning / CodeQL

Binding a socket to all network interfaces Medium

'' binds a socket to all interfaces.

Copilot Autofix AI 4 months ago

To fix the problem, we need to bind the socket to a specific interface instead of all interfaces. This can be achieved by replacing the empty string ("") with a specific IP address. If the specific IP address is not known or needs to be configurable, we can use an environment variable to set it.

  1. Modify the assign_port function to accept an additional parameter for the IP address.
  2. Use this IP address to bind the socket instead of the empty string.
  3. Update the defaults dictionary to include a default IP address.
  4. Ensure the IP address is read from the environment variables.
Suggested changeset 1
libs/proxy/llmstudio_proxy/config.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libs/proxy/llmstudio_proxy/config.py b/libs/proxy/llmstudio_proxy/config.py
--- a/libs/proxy/llmstudio_proxy/config.py
+++ b/libs/proxy/llmstudio_proxy/config.py
@@ -8,3 +8,3 @@
 
-def assign_port(default_port=None):
+def assign_port(ip_address, default_port=None):
     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -12,9 +12,9 @@
             if default_port is not None:
-                s.bind(("", default_port))
+                s.bind((ip_address, default_port))
                 return default_port
             else:
-                s.bind(("", 0))
+                s.bind((ip_address, 0))
                 return s.getsockname()[1]
         except OSError:
-            s.bind(("", 0))
+            s.bind((ip_address, 0))
             return s.getsockname()[1]
@@ -24,3 +24,3 @@
     "LLMSTUDIO_ENGINE_HOST": "localhost",
-    "LLMSTUDIO_ENGINE_PORT": str(assign_port(50001)),
+    "LLMSTUDIO_ENGINE_PORT": str(assign_port("127.0.0.1", 50001)),
 }
@@ -30,2 +30,8 @@
 
+ENGINE_HOST = os.environ["LLMSTUDIO_ENGINE_HOST"]
+ENGINE_PORT = os.environ["LLMSTUDIO_ENGINE_PORT"]
+
+# Update the assign_port call to use the environment variable for the IP address
+ENGINE_PORT = str(assign_port(ENGINE_HOST, int(ENGINE_PORT)))
+
 ENGINE_HOST = os.environ["LLMSTUDIO_ENGINE_HOST"]
EOF
@@ -8,3 +8,3 @@

def assign_port(default_port=None):
def assign_port(ip_address, default_port=None):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -12,9 +12,9 @@
if default_port is not None:
s.bind(("", default_port))
s.bind((ip_address, default_port))
return default_port
else:
s.bind(("", 0))
s.bind((ip_address, 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))
s.bind((ip_address, 0))
return s.getsockname()[1]
@@ -24,3 +24,3 @@
"LLMSTUDIO_ENGINE_HOST": "localhost",
"LLMSTUDIO_ENGINE_PORT": str(assign_port(50001)),
"LLMSTUDIO_ENGINE_PORT": str(assign_port("127.0.0.1", 50001)),
}
@@ -30,2 +30,8 @@

ENGINE_HOST = os.environ["LLMSTUDIO_ENGINE_HOST"]
ENGINE_PORT = os.environ["LLMSTUDIO_ENGINE_PORT"]

# Update the assign_port call to use the environment variable for the IP address
ENGINE_PORT = str(assign_port(ENGINE_HOST, int(ENGINE_PORT)))

ENGINE_HOST = os.environ["LLMSTUDIO_ENGINE_HOST"]
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
s.bind(("", default_port))
return default_port
else:
s.bind(("", 0))

Check warning

Code scanning / CodeQL

Binding a socket to all network interfaces Medium

'' binds a socket to all interfaces.

Copilot Autofix AI 4 months ago

To fix the problem, we need to bind the socket to a specific interface instead of all interfaces. This can be achieved by using a dedicated IP address for the interface we want to bind to. If the specific interface is not known or needs to be configurable, we can use an environment variable to specify the interface.

  1. Modify the assign_port function to accept an additional parameter for the interface IP address.
  2. Use this parameter to bind the socket to the specified interface instead of all interfaces.
  3. Update the code to use a default interface IP address if none is provided.
Suggested changeset 1
libs/proxy/llmstudio_proxy/config.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libs/proxy/llmstudio_proxy/config.py b/libs/proxy/llmstudio_proxy/config.py
--- a/libs/proxy/llmstudio_proxy/config.py
+++ b/libs/proxy/llmstudio_proxy/config.py
@@ -8,3 +8,3 @@
 
-def assign_port(default_port=None):
+def assign_port(default_port=None, interface_ip="127.0.0.1"):
     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -12,9 +12,9 @@
             if default_port is not None:
-                s.bind(("", default_port))
+                s.bind((interface_ip, default_port))
                 return default_port
             else:
-                s.bind(("", 0))
+                s.bind((interface_ip, 0))
                 return s.getsockname()[1]
         except OSError:
-            s.bind(("", 0))
+            s.bind((interface_ip, 0))
             return s.getsockname()[1]
@@ -24,3 +24,3 @@
     "LLMSTUDIO_ENGINE_HOST": "localhost",
-    "LLMSTUDIO_ENGINE_PORT": str(assign_port(50001)),
+    "LLMSTUDIO_ENGINE_PORT": str(assign_port(50001, os.getenv("LLMSTUDIO_INTERFACE_IP", "127.0.0.1"))),
 }
EOF
@@ -8,3 +8,3 @@

def assign_port(default_port=None):
def assign_port(default_port=None, interface_ip="127.0.0.1"):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -12,9 +12,9 @@
if default_port is not None:
s.bind(("", default_port))
s.bind((interface_ip, default_port))
return default_port
else:
s.bind(("", 0))
s.bind((interface_ip, 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))
s.bind((interface_ip, 0))
return s.getsockname()[1]
@@ -24,3 +24,3 @@
"LLMSTUDIO_ENGINE_HOST": "localhost",
"LLMSTUDIO_ENGINE_PORT": str(assign_port(50001)),
"LLMSTUDIO_ENGINE_PORT": str(assign_port(50001, os.getenv("LLMSTUDIO_INTERFACE_IP", "127.0.0.1"))),
}
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
s.bind(("", 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))

Check warning

Code scanning / CodeQL

Binding a socket to all network interfaces Medium

'' binds a socket to all interfaces.

Copilot Autofix AI 4 months ago

To fix the problem, we should bind the socket to a specific interface rather than all interfaces. This can be achieved by replacing the empty string ("") with a specific IP address. In this case, we will use localhost (i.e., 127.0.0.1) to restrict the socket to the local machine. This change will ensure that the socket only accepts connections from the local machine, thereby enhancing security.

Suggested changeset 1
libs/proxy/llmstudio_proxy/config.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libs/proxy/llmstudio_proxy/config.py b/libs/proxy/llmstudio_proxy/config.py
--- a/libs/proxy/llmstudio_proxy/config.py
+++ b/libs/proxy/llmstudio_proxy/config.py
@@ -12,9 +12,9 @@
             if default_port is not None:
-                s.bind(("", default_port))
+                s.bind(("127.0.0.1", default_port))
                 return default_port
             else:
-                s.bind(("", 0))
+                s.bind(("127.0.0.1", 0))
                 return s.getsockname()[1]
         except OSError:
-            s.bind(("", 0))
+            s.bind(("127.0.0.1", 0))
             return s.getsockname()[1]
EOF
@@ -12,9 +12,9 @@
if default_port is not None:
s.bind(("", default_port))
s.bind(("127.0.0.1", default_port))
return default_port
else:
s.bind(("", 0))
s.bind(("127.0.0.1", 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))
s.bind(("127.0.0.1", 0))
return s.getsockname()[1]
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
if default_port is not None:
s.bind(("", default_port))

Check warning

Code scanning / CodeQL

Binding a socket to all network interfaces Medium

'' binds a socket to all interfaces.

Copilot Autofix AI 4 months ago

To fix the problem, we need to bind the socket to a specific network interface instead of all interfaces. This can be achieved by replacing the empty string "" with a specific IP address. In this case, we will use the LLMSTUDIO_TRACKING_HOST environment variable, which defaults to localhost. This ensures that the socket is only accessible from the local machine, mitigating the security risk.

  1. Modify the assign_port function to accept an additional parameter for the host.
  2. Use the TRACKING_HOST environment variable as the host when binding the socket.
Suggested changeset 1
libs/tracker/llmstudio_tracker/config.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libs/tracker/llmstudio_tracker/config.py b/libs/tracker/llmstudio_tracker/config.py
--- a/libs/tracker/llmstudio_tracker/config.py
+++ b/libs/tracker/llmstudio_tracker/config.py
@@ -8,3 +8,3 @@
 
-def assign_port(default_port=None):
+def assign_port(host, default_port=None):
     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -12,9 +12,9 @@
             if default_port is not None:
-                s.bind(("", default_port))
+                s.bind((host, default_port))
                 return default_port
             else:
-                s.bind(("", 0))
+                s.bind((host, 0))
                 return s.getsockname()[1]
         except OSError:
-            s.bind(("", 0))
+            s.bind((host, 0))
             return s.getsockname()[1]
@@ -24,3 +24,3 @@
     "LLMSTUDIO_TRACKING_HOST": "localhost",
-    "LLMSTUDIO_TRACKING_PORT": str(assign_port(50002)),
+    "LLMSTUDIO_TRACKING_PORT": str(assign_port(os.getenv("LLMSTUDIO_TRACKING_HOST", "localhost"), 50002)),
     "LLMSTUDIO_TRACKING_URI": "sqlite:///./llmstudio_mgmt.db",
EOF
@@ -8,3 +8,3 @@

def assign_port(default_port=None):
def assign_port(host, default_port=None):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -12,9 +12,9 @@
if default_port is not None:
s.bind(("", default_port))
s.bind((host, default_port))
return default_port
else:
s.bind(("", 0))
s.bind((host, 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))
s.bind((host, 0))
return s.getsockname()[1]
@@ -24,3 +24,3 @@
"LLMSTUDIO_TRACKING_HOST": "localhost",
"LLMSTUDIO_TRACKING_PORT": str(assign_port(50002)),
"LLMSTUDIO_TRACKING_PORT": str(assign_port(os.getenv("LLMSTUDIO_TRACKING_HOST", "localhost"), 50002)),
"LLMSTUDIO_TRACKING_URI": "sqlite:///./llmstudio_mgmt.db",
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
s.bind(("", default_port))
return default_port
else:
s.bind(("", 0))

Check warning

Code scanning / CodeQL

Binding a socket to all network interfaces Medium

'' binds a socket to all interfaces.

Copilot Autofix AI 4 months ago

To fix the problem, we need to bind the socket to a specific interface instead of all interfaces. This can be achieved by replacing the empty string "" with a specific IP address, such as 127.0.0.1 (localhost), which limits the socket to accept connections only from the local machine.

  • Update the assign_port function to bind the socket to 127.0.0.1 instead of "".
  • Ensure that the changes do not affect the existing functionality of dynamically assigning a port.
Suggested changeset 1
libs/tracker/llmstudio_tracker/config.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libs/tracker/llmstudio_tracker/config.py b/libs/tracker/llmstudio_tracker/config.py
--- a/libs/tracker/llmstudio_tracker/config.py
+++ b/libs/tracker/llmstudio_tracker/config.py
@@ -12,9 +12,9 @@
             if default_port is not None:
-                s.bind(("", default_port))
+                s.bind(("127.0.0.1", default_port))
                 return default_port
             else:
-                s.bind(("", 0))
+                s.bind(("127.0.0.1", 0))
                 return s.getsockname()[1]
         except OSError:
-            s.bind(("", 0))
+            s.bind(("127.0.0.1", 0))
             return s.getsockname()[1]
EOF
@@ -12,9 +12,9 @@
if default_port is not None:
s.bind(("", default_port))
s.bind(("127.0.0.1", default_port))
return default_port
else:
s.bind(("", 0))
s.bind(("127.0.0.1", 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))
s.bind(("127.0.0.1", 0))
return s.getsockname()[1]
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
s.bind(("", 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))

Check warning

Code scanning / CodeQL

Binding a socket to all network interfaces Medium

'' binds a socket to all interfaces.

Copilot Autofix AI 4 months ago

To fix the problem, we need to bind the socket to a specific network interface instead of all interfaces. This can be achieved by replacing the empty string ("") with a specific IP address. In this case, we will use localhost (127.0.0.1) to bind the socket to the local interface, which is a common practice for services that do not need to be accessed from outside the host machine.

  • Update the assign_port function to bind the socket to 127.0.0.1 instead of an empty string.
  • Ensure that the socket is only accessible from the local machine, enhancing security.
Suggested changeset 1
libs/tracker/llmstudio_tracker/config.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/libs/tracker/llmstudio_tracker/config.py b/libs/tracker/llmstudio_tracker/config.py
--- a/libs/tracker/llmstudio_tracker/config.py
+++ b/libs/tracker/llmstudio_tracker/config.py
@@ -12,9 +12,9 @@
             if default_port is not None:
-                s.bind(("", default_port))
+                s.bind(("127.0.0.1", default_port))
                 return default_port
             else:
-                s.bind(("", 0))
+                s.bind(("127.0.0.1", 0))
                 return s.getsockname()[1]
         except OSError:
-            s.bind(("", 0))
+            s.bind(("127.0.0.1", 0))
             return s.getsockname()[1]
EOF
@@ -12,9 +12,9 @@
if default_port is not None:
s.bind(("", default_port))
s.bind(("127.0.0.1", default_port))
return default_port
else:
s.bind(("", 0))
s.bind(("127.0.0.1", 0))
return s.getsockname()[1]
except OSError:
s.bind(("", 0))
s.bind(("127.0.0.1", 0))
return s.getsockname()[1]
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
@diogoncalves diogoncalves changed the title Modularization lift and shift VERSION 1.0.0 Oct 22, 2024
@diogoncalves diogoncalves changed the title VERSION 1.0.0 VERSION 1.0.0b1 Oct 25, 2024
@claudiolemos claudiolemos merged commit 2ab49bc into main Oct 28, 2024
3 checks passed
@claudiolemos claudiolemos deleted the feat/modularization_shift_and_lift branch October 28, 2024 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants