Skip to content

Commit

Permalink
feat: fetch LLM API keys from user env variables (#102)
Browse files Browse the repository at this point in the history
<!-- Suggested PR Title: [feat/fix/refactor/perf/test/ci/docs/chore]
brief description of the change -->
<!-- Please follow Conventional Commits:
https://www.conventionalcommits.org/en/v1.0.0/ -->

## Description
This pull request fixes the handling of API keys for LLMs in the code.
It adds a JavaScript script to handle the API keys for LLMs and
initializes the LLM secrets in the MAIDR instance. The script injects
the LLM API keys into the MAIDR instance and sets the appropriate
settings based on the presence of the Gemini and OpenAI API keys. This
ensures that the LLM functionality works correctly with the updated API
key handling.

closes #76 

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Documentation update

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] Any dependent changes have been merged and published in downstream
modules

# Pull Request

## Description
1. Added a new method called `initialize_llm_secrets()` in
environment.py which fetches the keys from the environment variable.
2. Injected the script when the maidr iframe loads initially.

## Checklist
<!-- Please select all applicable options. -->
<!-- To select your options, please put an 'x' in the all boxes that
apply. -->

- [x] I have read the [Contributor Guidelines](../CONTRIBUTING.md).
- [x] I have performed a self-review of my own code and ensured it
follows the project's coding standards.
- [x] I have tested the changes locally following
`ManualTestingProcess.md`, and all tests related to this pull request
pass.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation, if applicable.
- [x] I have added appropriate unit tests, if applicable.

## Additional Notes
<!-- Add any additional notes or comments here. -->
<!-- Template credit: This pull request template is based on Embedded
Artistry
{https://github.com/embeddedartistry/templates/blob/master/.github/PULL_REQUEST_TEMPLATE.md},
Clowder
{https://github.com/clowder-framework/clowder/blob/develop/.github/PULL_REQUEST_TEMPLATE.md},
and TalAter {https://github.com/TalAter/open-source-templates}
templates. -->
  • Loading branch information
dakshpokar authored Sep 13, 2024
1 parent ae7bc15 commit fc84593
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 5 deletions.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,34 @@ Python binder for maidr library

## Install and Upgrade

``` sh
```sh
# install the latest release from PyPI
pip install -U maidr

# or install the development version from GitHub
pip install -U git+https://github.com/xability/py_maidr.git
```

## LLM Configuration for Interactive Shell

To use OpenAI or Gemini Models along with the maidr library, follow the steps below:

1. Signup and get the API Keys for OpenAI or Gemini Models.
2. Add the keys to environment variables so that python binder can access the keys.
(Note: This only temporarily adds keys in environment variable, for persistent access you might want to add the export command to your shell configuration)

##### Mac Configuration

```bash
export OPENAI_API_KEY="<< add you key here >>"
export GEMINI_API_KEY="<< add you key here >>"
```

##### Windows Configuration

```
setx OPENAI_API_KEY "<< add you key here >>"
setx GEMINI_API_KEY "<< add you key here >>"
```

3. Run your python program.
11 changes: 7 additions & 4 deletions maidr/core/maidr.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
from __future__ import annotations

from typing import Literal

import io
import json
import uuid
from typing import Literal

from htmltools import HTML, HTMLDocument, Tag, tags
from lxml import etree

from matplotlib.figure import Figure

from maidr.core.context_manager import HighlightContextManager
from maidr.core.plot import MaidrPlot
from maidr.util.environment import Environment


class Maidr:
Expand Down Expand Up @@ -170,8 +169,11 @@ def _inject_plot(plot: HTML, maidr: str) -> Tag:
tags.script(maidr),
)

unique_id = "iframe_" + Maidr._unique_id()

# Embed the rendering into an iFrame for proper working of JS library.
base_html = tags.iframe(
id=unique_id,
srcdoc=str(base_html.get_html_string()),
width="100%",
height="100%",
Expand All @@ -181,7 +183,8 @@ def _inject_plot(plot: HTML, maidr: str) -> Tag:
onload="""
this.style.height = this.contentWindow.document.body.scrollHeight +
100 + 'px';
""",
"""
+ Environment.initialize_llm_secrets(unique_id),
)

return base_html
69 changes: 69 additions & 0 deletions maidr/util/environment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import json
import os


class Environment:
@staticmethod
def is_interactive_shell() -> bool:
Expand All @@ -11,3 +15,68 @@ def is_interactive_shell() -> bool:
)
except ImportError:
return False

@staticmethod
def initialize_llm_secrets(unique_id: str) -> str:
"""Inject the LLM API keys into the MAIDR instance."""

gemini_api_key = os.getenv("GEMINI_API_KEY")
openai_api_key = os.getenv("OPENAI_API_KEY")

# Default settings for the MAIDR instance
settings = {
"vol": "0.5",
"autoPlayRate": "500",
"brailleDisplayLength": "32",
"colorSelected": "#03c809",
"MIN_FREQUENCY": "200",
"MAX_FREQUENCY": "1000",
"keypressInterval": "2000",
"ariaMode": "assertive",
"openAIAuthKey": "",
"geminiAuthKey": "",
"skillLevel": "basic",
"skillLevelOther": "",
"LLMModel": "openai",
"LLMPreferences": "",
"LLMOpenAiMulti": False,
"LLMGeminiMulti": False,
"autoInitLLM": True,
}

if gemini_api_key is not None and openai_api_key is not None:
settings["geminiAuthKey"] = gemini_api_key
settings["openAIAuthKey"] = openai_api_key
settings["LLMOpenAiMulti"] = True
settings["LLMGeminiMulti"] = True
settings["LLMModel"] = "multi"
elif openai_api_key is not None:
settings["LLMOpenAiMulti"] = True
settings["openAIAuthKey"] = openai_api_key
settings["LLMModel"] = "openai"
elif gemini_api_key is not None:
settings["LLMGeminiMulti"] = True
settings["geminiAuthKey"] = gemini_api_key
settings["LLMModel"] = "gemini"

settings_data = json.dumps(settings)

keys_injection_script = f"""
function addKeyValueLocalStorage(iframeId, key, value) {{
const iframe = document.getElementById(iframeId);
if (iframe && iframe.contentWindow) {{
try {{
iframe.contentWindow.localStorage.setItem(key, value);
}} catch (error) {{
console.error('Error accessing iframe localStorage:', error);
}}
}} else {{
console.error('Iframe not found or inaccessible.');
}}
}}
addKeyValueLocalStorage(
'{unique_id}', 'settings_data', JSON.stringify({settings_data})
);
"""

return keys_injection_script

0 comments on commit fc84593

Please sign in to comment.