Skip to content

Commit 88eae05

Browse files
authored
2.0.0 (#28)
2 parents 94f2d56 + 733bfb1 commit 88eae05

File tree

18 files changed

+198
-109
lines changed

18 files changed

+198
-109
lines changed

.github/workflows/license_tests.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,3 @@ on:
55
jobs:
66
license_tests:
77
uses: neongeckocom/.github/.github/workflows/license_tests.yml@master
8-
with:
9-
packages-exclude: '^(precise-runner|fann2|tqdm|bs4|neon-core|nvidia|neon-skill-fallback|bitstruct).*'

.github/workflows/update_skill_json.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
name: Update skill.json
44
on:
55
push:
6+
branches-ignore:
7+
- XLATE_**
68

79
jobs:
810
update_skill_json:

.gitignore

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ parts/
2020
sdist/
2121
var/
2222
wheels/
23-
pip-wheel-metadata/
2423
share/python-wheels/
2524
*.egg-info/
2625
.installed.cfg
@@ -50,6 +49,7 @@ coverage.xml
5049
*.py,cover
5150
.hypothesis/
5251
.pytest_cache/
52+
cover/
5353

5454
# Translations
5555
*.mo
@@ -72,6 +72,7 @@ instance/
7272
docs/_build/
7373

7474
# PyBuilder
75+
.pybuilder/
7576
target/
7677

7778
# Jupyter Notebook
@@ -82,7 +83,9 @@ profile_default/
8283
ipython_config.py
8384

8485
# pyenv
85-
.python-version
86+
# For a library or package, you might want to ignore these files since the code is
87+
# intended to run in multiple environments; otherwise, check them in:
88+
# .python-version
8689

8790
# pipenv
8891
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
@@ -91,7 +94,24 @@ ipython_config.py
9194
# install all needed dependencies.
9295
#Pipfile.lock
9396

94-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
97+
# poetry
98+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99+
# This is especially recommended for binary packages to ensure reproducibility, and is more
100+
# commonly ignored for libraries.
101+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102+
#poetry.lock
103+
104+
# pdm
105+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106+
#pdm.lock
107+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108+
# in version control.
109+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
110+
.pdm.toml
111+
.pdm-python
112+
.pdm-build/
113+
114+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
95115
__pypackages__/
96116

97117
# Celery stuff
@@ -127,3 +147,16 @@ dmypy.json
127147

128148
# Pyre type checker
129149
.pyre/
150+
151+
# pytype static type analyzer
152+
.pytype/
153+
154+
# Cython debug symbols
155+
cython_debug/
156+
157+
# PyCharm
158+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
159+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
160+
# and can be added to the global gitignore or merged into this file. For a more nuclear
161+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
162+
#.idea/

CHANGELOG.md

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,60 @@
11
# Changelog
22

3-
## [1.0.1a2](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.1a2) (2023-10-11)
3+
## [1.0.2a7](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.2a7) (2025-03-20)
44

5-
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.1a1...1.0.1a2)
5+
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.2a6...1.0.2a7)
66

77
**Merged pull requests:**
88

9-
- More vocab option handling [\#16](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/16) ([NeonDaniel](https://github.com/NeonDaniel))
9+
- Update dependencies [\#27](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/27) ([NeonDaniel](https://github.com/NeonDaniel))
1010

11-
## [1.0.1a1](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.1a1) (2023-09-27)
11+
## [1.0.2a6](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.2a6) (2025-03-11)
1212

13-
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.0...1.0.1a1)
13+
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.2a5...1.0.2a6)
1414

1515
**Merged pull requests:**
1616

17-
- Update "Chat GPT" vocab from testing feedback [\#15](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/15) ([NeonDaniel](https://github.com/NeonDaniel))
17+
- Update automation, gitignore, and license notices [\#26](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/26) ([NeonDaniel](https://github.com/NeonDaniel))
18+
19+
## [1.0.2a5](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.2a5) (2024-09-17)
20+
21+
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.2a4...1.0.2a5)
22+
23+
**Merged pull requests:**
24+
25+
- Update OVOS depdendencies for 0.x compat [\#25](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/25) ([NeonDaniel](https://github.com/NeonDaniel))
26+
27+
## [1.0.2a4](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.2a4) (2024-07-18)
28+
29+
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.2a3...1.0.2a4)
30+
31+
**Merged pull requests:**
32+
33+
- Update fallback\_llm intents [\#18](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/18) ([NeonClary](https://github.com/NeonClary))
34+
35+
## [1.0.2a3](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.2a3) (2024-03-26)
36+
37+
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.2a2...1.0.2a3)
38+
39+
**Merged pull requests:**
40+
41+
- Extend FallbackSkill from ovos-workshop and use Hana endpoints [\#21](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/21) ([NeonDaniel](https://github.com/NeonDaniel))
42+
43+
## [1.0.2a2](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.2a2) (2024-02-05)
44+
45+
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.2a1...1.0.2a2)
46+
47+
**Merged pull requests:**
48+
49+
- Support ovos-utils 0.1 [\#20](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/20) ([NeonDaniel](https://github.com/NeonDaniel))
50+
51+
## [1.0.2a1](https://github.com/NeonGeckoCom/skill-fallback_llm/tree/1.0.2a1) (2024-01-03)
52+
53+
[Full Changelog](https://github.com/NeonGeckoCom/skill-fallback_llm/compare/1.0.1...1.0.2a1)
54+
55+
**Merged pull requests:**
56+
57+
- Refactor for better compat. with OVOS dependencies [\#19](https://github.com/NeonGeckoCom/skill-fallback_llm/pull/19) ([NeonDaniel](https://github.com/NeonDaniel))
1858

1959

2060

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# NEON AI (TM) SOFTWARE, Software Development Kit & Application Development System
22
# All trademark and other rights reserved by their respective owners
3-
# Copyright 2008-2021 Neongecko.com Inc.
3+
# Copyright 2008-2025 Neongecko.com Inc.
44
# BSD-3 License
55

66
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the

__init__.py

Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# NEON AI (TM) SOFTWARE, Software Development Kit & Application Framework
22
# All trademark and other rights reserved by their respective owners
3-
# Copyright 2008-2022 Neongecko.com Inc.
3+
# Copyright 2008-2025 Neongecko.com Inc.
44
# Contributors: Daniel McKnight, Guy Daniels, Elon Gasper, Richard Leeds,
55
# Regina Bloomstine, Casimiro Ferreira, Andrii Pernatii, Kirill Hrymailo
66
# BSD-3 License
@@ -25,36 +25,37 @@
2525
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2626
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2727
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
2829
from enum import Enum
2930
from threading import Thread
3031
from time import time
3132

3233
from lingua_franca.format import nice_duration
33-
from ovos_bus_client import Message
34+
from ovos_bus_client.message import Message
3435
from ovos_utils import classproperty
3536
from ovos_utils.log import LOG
3637
from ovos_utils.process_utils import RuntimeRequirements
37-
# from ovos_workshop.skills.fallback import FallbackSkill
38-
from neon_utils.skills.neon_fallback_skill import NeonFallbackSkill, NeonSkill
39-
from neon_utils.message_utils import get_message_user
38+
from ovos_workshop.skills.fallback import FallbackSkill
39+
from ovos_workshop.decorators import intent_handler, fallback_handler
40+
from neon_utils.message_utils import get_message_user, dig_for_message
4041
from neon_utils.user_utils import get_user_prefs
42+
from neon_utils.hana_utils import request_backend
4143
from neon_mq_connector.utils.client_utils import send_mq_request
4244

43-
from mycroft.skills.mycroft_skill.decorators import intent_handler
44-
4545

4646
class LLM(Enum):
4747
GPT = "Chat GPT"
4848
FASTCHAT = "FastChat"
4949

5050

51-
class LLMSkill(NeonFallbackSkill):
52-
def __init__(self, **kwargs):
53-
NeonFallbackSkill.__init__(self, **kwargs)
51+
class LLMSkill(FallbackSkill):
52+
def __init__(self, *args, **kwargs):
53+
super().__init__(*args, **kwargs)
5454
self.chat_history = dict()
5555
self._default_user = "local"
5656
self._default_llm = LLM.FASTCHAT
5757
self.chatting = dict()
58+
self.register_entity_file("llm.entity")
5859

5960
@classproperty
6061
def runtime_requirements(self):
@@ -76,35 +77,36 @@ def chat_timeout_seconds(self):
7677
def fallback_enabled(self):
7778
return self.settings.get("fallback_enabled", False)
7879

79-
# TODO: Move to __init__ after ovos-workshop stable release
80-
def initialize(self):
81-
self.register_entity_file("llm.entity")
82-
# TODO: Resolve Padatious entity file handling bug
83-
if self.fallback_enabled:
84-
self.register_fallback(self.fallback_llm, 85)
85-
80+
@fallback_handler(85)
8681
def fallback_llm(self, message):
82+
if not self.fallback_enabled:
83+
LOG.info("LLM Fallback Disabled")
84+
return False
8785
utterance = message.data['utterance']
86+
LOG.info(f"Getting LLM response to: {utterance}")
8887
user = get_message_user(message) or self._default_user
89-
answer = self._get_llm_response(utterance, user, self._default_llm)
90-
if not answer:
91-
LOG.info(f"No fallback response")
92-
return False
93-
self.speak(answer)
88+
89+
def _threaded_get_response(utt, usr):
90+
answer = self._get_llm_response(utt, usr, self._default_llm)
91+
if not answer:
92+
LOG.info(f"No fallback response")
93+
return
94+
self.speak(answer)
95+
96+
# TODO: Speak filler?
97+
Thread(target=_threaded_get_response, args=(utterance, user), daemon=True).start()
9498
return True
9599

96100
@intent_handler("enable_fallback.intent")
97101
def handle_enable_fallback(self, message):
98102
if not self.fallback_enabled:
99103
self.settings['fallback_enabled'] = True
100-
self.register_fallback(self.fallback_llm, 85)
101104
self.speak_dialog("fallback_enabled")
102105

103106
@intent_handler("disable_fallback.intent")
104107
def handle_disable_fallback(self, message):
105108
if self.fallback_enabled:
106109
self.settings['fallback_enabled'] = False
107-
self.remove_fallback(self.fallback_llm)
108110
self.speak_dialog("fallback_disabled")
109111

110112
@intent_handler("ask_llm.intent")
@@ -127,8 +129,7 @@ def handle_chat_with_llm(self, message):
127129
llm = self._get_requested_llm(message)
128130
timeout_duration = nice_duration(self.chat_timeout_seconds)
129131
self.speak_dialog("start_chat", {"llm": llm.value,
130-
"timeout": timeout_duration},
131-
private=True)
132+
"timeout": timeout_duration})
132133
self._reset_expiration(user, llm)
133134

134135
@intent_handler("email_chat_history.intent")
@@ -138,15 +139,15 @@ def handle_email_chat_history(self, message):
138139
email_addr = user_prefs['email']
139140
if username not in self.chat_history:
140141
LOG.debug(f"No history for {username}")
141-
self.speak_dialog("no_chat_history", private=True)
142+
self.speak_dialog("no_chat_history")
142143
return
143144
if not email_addr:
144145
LOG.debug("No email address")
145146
# TODO: Capture Email address
146-
self.speak_dialog("no_email_address", private=True)
147+
self.speak_dialog("no_email_address")
147148
return
148149
self.speak_dialog("sending_chat_history",
149-
{"email": email_addr}, private=True)
150+
{"email": email_addr})
150151
self._send_email(username, email_addr)
151152

152153
def _send_email(self, username: str, email: str):
@@ -155,8 +156,7 @@ def _send_email(self, username: str, email: str):
155156
for entry in history:
156157
formatted = entry[1].replace('\n\n', '\n').replace('\n', '\n\t...')
157158
email_text += f"[{entry[0]}] {formatted}\n"
158-
NeonSkill.send_email(self, "LLM Conversation", email_text,
159-
email_addr=email)
159+
self.send_email("LLM Conversation", email_text, email_addr=email)
160160

161161
def _stop_chatting(self, message):
162162
user = get_message_user(message) or self._default_user
@@ -174,16 +174,15 @@ def _get_llm_response(self, query: str, user: str, llm: LLM) -> str:
174174
:returns: Speakable response to the user's query
175175
"""
176176
if llm == LLM.GPT:
177-
queue = "chat_gpt_input"
177+
endpoint = "chatgpt"
178178
elif llm == LLM.FASTCHAT:
179-
queue = "fastchat_input"
179+
endpoint = "fastchat"
180180
else:
181181
raise ValueError(f"Expected LLM, got: {llm}")
182182
self.chat_history.setdefault(user, list())
183-
mq_resp = send_mq_request("/llm", {"query": query,
184-
"history": self.chat_history[user]},
185-
queue)
186-
resp = mq_resp.get("response") or ""
183+
resp = request_backend(f"/llm/{endpoint}", {"query": query, "history": self.chat_history[user]})
184+
185+
resp = resp.get("response") or ""
187186
if resp:
188187
username = "user" if user == self._default_user else user
189188
self.chat_history[user].append((username, query))
@@ -237,3 +236,38 @@ def _reset_expiration(self, user, llm):
237236
self.cancel_scheduled_event(event_name)
238237
self.schedule_event(self._stop_chatting, self.chat_timeout_seconds,
239238
{'user': user}, event_name)
239+
240+
# TODO: copied from NeonSkill. This method should be moved to a standalone
241+
# utility
242+
def send_email(self, title, body, message=None, email_addr=None,
243+
attachments=None):
244+
"""
245+
Send an email to the registered user's email.
246+
Method here for backwards compatibility with Mycroft skills.
247+
Email address priority: email_addr, user prefs from message,
248+
fallback to DeviceApi for Mycroft method
249+
250+
Arguments:
251+
title (str): Title of email
252+
body (str): HTML body of email. This supports
253+
simple HTML like bold and italics
254+
email_addr (str): Optional email address to send message to
255+
attachments (dict): Optional dict of file names to Base64 encoded files
256+
message (Message): Optional message to get email from
257+
"""
258+
message = message or dig_for_message()
259+
if not email_addr and message:
260+
email_addr = get_user_prefs(message)["user"].get("email")
261+
262+
if email_addr and send_mq_request:
263+
LOG.info("Send email via Neon Server")
264+
request_data = {"recipient": email_addr,
265+
"subject": title,
266+
"body": body,
267+
"attachments": attachments}
268+
data = send_mq_request("/neon_emails", request_data,
269+
"neon_emails_input")
270+
return data.get("success")
271+
else:
272+
LOG.warning("Attempting to send email via Mycroft Backend")
273+
super().send_email(title, body)

locale/en-us/intent/ask_llm.intent

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
(ask|tell) (chatgpt|chat gpt|chat g p t|chat gpg|chat gptc|jack gpt|jack chi pt|fast chat|fastchat) {question}
1+
(ask|tell|task|half|sjet|asked|as) (chatgpt|chat gpt|chat g p t|chat gpg|chat gptc|jackgpt|jack gpt|jack chi pt|fast chat|fastchat|chat gbt|chatgbt|chat gpt4|chatgpt4|a language model|an llm) {question}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
(i want to |)(chat|talk|converse|start a conversation) (to|with) (chat gpt|chat g p t|chat gpg|chatgpt|jack gpt|jack chi pt|fastchat|fast chat)
1+
(i want to |)(chat|talk|converse|start a conversation) (to|with) (chatgpt|chat gpt|chat g p t|chat gpg|chat gptc|jackgpt|jack gpt|jack chi pt|fast chat|fastchat|chat gbt|chatgbt|chat gpt4|chatgpt4|a language model|an llm)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
disable (llm|chatgpt|chat gpt|chat g p t|chat gpg) (fallback|fall back)( skill|)
1+
disable (llm|chatgpt|chat gpt|chat g p t|chat gpg|chat gptc|jackgpt|jack gpt|jack chi pt|fast chat|fastchat|chat gbt|chatgbt|chat gpt4|chatgpt4|language model) (fallback|fall back)( skill|)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
enable (llm|chatgpt|chat gpt|chat g p t|chat gpg) (fallback|fall back)( skill|)
1+
enable (llm|chatgpt|chat gpt|chat g p t|chat gpg|chat gptc|jackgpt|jack gpt|jack chi pt|fast chat|fastchat|chat gbt|chatgbt|chat gpt4|chatgpt4|language model) (fallback|fall back)( skill|)

0 commit comments

Comments
 (0)