Skip to content

Commit 17d448e

Browse files
authored
Add authentication for local (#3)
* Add teamspace configuration and authentication method to LLM class * Refactor LLM class by removing teamspace validation and unused authentication call; add unit tests for authentication method * fix pre-commit * Update README for clarity on Lightning Studio usage and local authentication; modify LLM class authentication method signature to accept optional parameters. * update
1 parent 701483f commit 17d448e

File tree

3 files changed

+52
-12
lines changed

3 files changed

+52
-12
lines changed

README.md

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pip install litai
5050

5151
## Run on a Studio
5252

53-
When running inside Lightning Studio, authentication is handled automatically. You can use any available LLM for text generation.
53+
When running inside Lightning Studio, you can use any available LLM out of the box — no extra setup required.
5454

5555
```python
5656
from litai import LLM
@@ -62,22 +62,14 @@ print(llm.chat("who are you?"))
6262

6363
## Run locally (outside Studio)
6464

65-
To use LitAI outside of Lightning Studio, youll need to manually authenticate using the following:
65+
To use LitAI outside of Lightning Studio, you'll need to explicitly provide your teamspace name.
6666

67-
- **teamspace** — Format: "owner-name/teamspace-name"
68-
(e.g. "username/my-team" or "org-name/my-team")
69-
- **lightning_api_key** — Your personal API key from Global Settings → Keys
70-
- **lightning_user_id** — Your Lightning user ID, also found in the Keys section
67+
The teamspace input format is: `"owner-name/teamspace-name"` (e.g. `"username/my-team"` or `"org-name/team-name"`)
7168

7269
```python
7370
from litai import LLM
7471

75-
llm = LLM(
76-
model="openai/gpt-4",
77-
teamspace="owner-name/teamspace-name",
78-
lightning_api_key="your-api-key",
79-
lightning_user_id="your-user-id",
80-
)
72+
llm = LLM(model="openai/gpt-4", teamspace="owner-name/teamspace-name")
8173
print(llm.chat("who are you?"))
8274
# I'm an AI by OpenAI
8375
```

src/litai/client.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from typing import Any, Dict, List, Optional, Union
2323

2424
import requests
25+
from lightning_sdk.lightning_cloud import login
2526
from lightning_sdk.llm import LLM as SDKLLM
2627

2728
from litai.tools import LitTool
@@ -111,6 +112,11 @@ def __init__(
111112
if lightning_user_id is not None:
112113
os.environ["LIGHTNING_USER_ID"] = lightning_user_id
113114

115+
if teamspace is None:
116+
teamspace = os.environ.get("LIGHTNING_TEAMSPACE")
117+
118+
self._authenticate(lightning_api_key, lightning_user_id)
119+
114120
if verbose not in [0, 1, 2]:
115121
raise ValueError("Verbose must be 0, 1, or 2.")
116122
self._verbose = verbose
@@ -134,6 +140,19 @@ def __init__(
134140

135141
threading.Thread(target=self._load_models, daemon=True).start()
136142

143+
def _authenticate(self, lightning_api_key: Optional[str], lightning_user_id: Optional[str]) -> None:
144+
if not (lightning_api_key and lightning_user_id):
145+
return
146+
auth = login.Auth()
147+
try:
148+
auth.authenticate()
149+
user_api_key = auth.api_key
150+
user_id = auth.user_id
151+
os.environ["LIGHTNING_API_KEY"] = user_api_key
152+
os.environ["LIGHTNING_USER_ID"] = user_id
153+
except ConnectionError as e:
154+
raise e
155+
137156
@property
138157
def model(self) -> str:
139158
"""Returns the main model name."""

tests/test_llm.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,32 @@ def test_get_history(monkeypatch, capsys):
255255
{"role": "user", "content": "Hello, world!", "model": "mock-model"},
256256
{"role": "assistant", "content": "I am a mock model!", "model": "mock-model"},
257257
]
258+
259+
260+
def test_authenticate_method(monkeypatch):
261+
# Mock the login.Auth class
262+
mock_auth = MagicMock()
263+
mock_auth.api_key = "test-api-key"
264+
mock_auth.user_id = "test-user-id"
265+
266+
def mock_auth_constructor():
267+
return mock_auth
268+
269+
monkeypatch.setattr("litai.client.login.Auth", mock_auth_constructor)
270+
271+
# Test case 1: Both api_key and user_id provided
272+
LLM(model="openai/gpt-4", lightning_api_key="my-key", lightning_user_id="my-user-id")
273+
274+
# Verify that the authentication was called
275+
mock_auth.authenticate.assert_called_once()
276+
277+
# Verify that environment variables were set
278+
assert os.getenv("LIGHTNING_API_KEY") == "test-api-key"
279+
assert os.getenv("LIGHTNING_USER_ID") == "test-user-id"
280+
281+
# Test case 2: Neither api_key nor user_id provided
282+
mock_auth.reset_mock()
283+
LLM(model="openai/gpt-4")
284+
285+
# Verify that authentication was not called
286+
mock_auth.authenticate.assert_not_called()

0 commit comments

Comments
 (0)