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

Development #143

Merged
merged 46 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7d1fa2d
removed gensim dependence
fractalego Jul 24, 2024
e245faf
generating the retrievers before saving the cache
fractalego Jul 24, 2024
09df1e3
Merge pull request #127 from fractalego/indexing-with-large-corpus
fractalego Jul 24, 2024
e7a92ce
added - before retrieved element
fractalego Jul 26, 2024
5c3a5ed
using a queue for the memory
fractalego Jul 26, 2024
f0fa731
memory facts are now queued
fractalego Jul 26, 2024
f5f0fb8
doubled the permitted token count in prediction
fractalego Aug 3, 2024
1502118
using entailer in test cases
fractalego Aug 3, 2024
902ad0f
fixed activation testcase
fractalego Aug 3, 2024
94c160e
using entailer to pre-filter the retrieved rules
fractalego Aug 4, 2024
64f365d
Merge pull request #128 from fractalego/indexing-with-large-corpus
fractalego Aug 4, 2024
c9e0e86
renamed dataclasses to dataobjects
fractalego Aug 4, 2024
306c7cc
Merge pull request #130 from fractalego/indexing-with-large-corpus
fractalego Aug 4, 2024
30e6036
added entailer model to the templates
fractalego Aug 4, 2024
148c8f3
fixed uncalled await
fractalego Aug 4, 2024
b1d45d4
Merge pull request #131 from fractalego/indexing-with-large-corpus
fractalego Aug 4, 2024
80b3907
awaiting function differently
fractalego Aug 4, 2024
f66d51a
Merge pull request #132 from fractalego/indexing-with-large-corpus
fractalego Aug 4, 2024
ed99325
reformatted
fractalego Aug 4, 2024
e002b93
saving remote connector
fractalego Aug 9, 2024
7f8b19e
refactored the backend configuration to a single host and port
fractalego Aug 9, 2024
3782e19
modified parameter for stopping the system while it is talking
fractalego Aug 9, 2024
9f5f0c2
removed logging elements
fractalego Oct 26, 2024
06b9073
Merge pull request #133 from fractalego/get-config-from-backend
fractalego Nov 1, 2024
c585e7c
renamed tts speaker
fractalego Nov 1, 2024
8aba6e4
another test for time pronunciation
fractalego Nov 1, 2024
60aaec1
Merge pull request #134 from fractalego/pronouncing-numbers
fractalego Nov 1, 2024
5835aac
the audio listener does not append user sentences while the interface…
fractalego Nov 10, 2024
27deffd
Merge pull request #135 from fractalego/bugfix/listener-active-while-…
fractalego Nov 10, 2024
7ea657a
the audio listener does not append user sentences while the interface…
fractalego Nov 10, 2024
a0b2b2b
Merge pull request #136 from fractalego/bugfix/listener-active-while-…
fractalego Nov 10, 2024
c51800e
allowing one-liner
fractalego Nov 10, 2024
95d20ac
Merge pull request #137 from fractalego/bugfix/listener-active-while-…
fractalego Nov 10, 2024
492097d
default entailer value
fractalego Nov 10, 2024
9084cea
Merge pull request #138 from fractalego/default-entailer-value
fractalego Nov 10, 2024
4cf5199
resetting rules and memory upon deactivation
fractalego Nov 11, 2024
11c9e35
Merge pull request #139 from fractalego/deactivate-resets-rules-and-m…
fractalego Nov 11, 2024
a5a67bd
Catching exections in the dialogue answerer. This is mainly due to ex…
fractalego Nov 23, 2024
99ff825
modified the prompt to include checks on the quality of the user's qu…
fractalego Nov 23, 2024
698992d
making tests work
fractalego Nov 23, 2024
4304ec2
Merge pull request #140 from fractalego/deactivate-resets-rules-and-m…
fractalego Nov 23, 2024
9ca70f6
updated the answer to an unknown prediction
fractalego Nov 23, 2024
3c9772c
Merge pull request #141 from fractalego/deactivate-resets-rules-and-m…
fractalego Nov 23, 2024
1de7c42
updated substitution exception logging within the assistant's interna…
fractalego Nov 24, 2024
cfd4844
removed extractors
fractalego Dec 15, 2024
16d7ee0
Merge pull request #142 from fractalego/removing-dead-code
fractalego Dec 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 32 additions & 46 deletions documentation/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,33 @@ A typical configuration file looks like this:

.. code-block:: text

{
"waking_up_word": "computer",
"waking_up_sound": true,
"deactivate_sound": true,
"rules": "rules.yaml",
"index": "indices.yaml",
"cache_filename": "knowledge_cache",
"prompt_filename": "main.prompt",
"functions": "functions.py",
"max_recursion": 2,
"llm_model": {
"model_host": "localhost",
"model_port": 8080,
"temperature": 0.4
},
"listener_model": {
"model_host": "localhost",
"model_port": 8080,
"listener_hotword_logp": -8,
"listener_volume_threshold": 0.6,
"listener_silence_timeout": 0.7
},
"speaker_model": {
"model_host": "localhost",
"model_port": 8080
},
"text_embedding_model": {
"model_host": "localhost",
"model_port": 8080
}
}
{
"waking_up_word": "computer",
"waking_up_sound": true,
"deactivate_sound": true,
"rules": "rules.yaml",
"index": "indices.yaml",
"cache_filename": "knowledge_cache",
"prompt_filename": "main.prompt",
"functions": "functions.py",
"max_recursion": 2,
"frontend_port": 8090,
"backend": {
"host": "localhost",
"port": 8080,
"token": "secret"
},
"generation_config": {
"temperature": 0.4
},
"listener_model": {
"listener_hotword_logp": -8,
"listener_volume_threshold": 0.6,
"listener_silence_timeout": 0.7,
"interruptible": true
}
}




Expand All @@ -59,20 +55,10 @@ These settings regulate the following:

* "frontend_port" is the port where the web frontend is running. The default is 8090.

* "llm_model" is the configuration to connect to wafl-llm in the backend. The default url is "localhost:8080". The "temperature" parameter is used to set the temperature for the LLM model. The default is 0.4.

* "listener_model" is the configuration to connect to the listener model in the backend. The default is "localhost:8080".

- The listener model is used to detect the wake-up word.
The similarity threshold for the detection can be set with the "listener_hotword_logp" parameter.

- The "listener_volume_threshold" parameter is used to set the volume threshold for any conversation.
Any word uttered with a volume below this threshold is ignored.

- The "listener_silence_timeout" parameter is used to set the silence timeout for any conversation.
If no word is uttered for a time longer than this timeout, the conversation is considered finished.

* "speaker_model" is the configuration to connect to the speaker model in the backend. The default is "localhost:8080".
* "backend" is the configuration related to the backend. The default is "localhost:8080".

* "text_embedding_model" is the configuration to connect to the text embedding model in the backend. The default is "localhost:8080".
* "generation_config" is the configuration related to the generation of the response. The default is "temperature: 0.4".

* "listener_model" is the configuration related to the listener model.
These items determine the thresholds for hotword detection, volume threshold, silence timeout, and whether the listener is interruptible.
The default is "listener_hotword_logp: -8", "listener_volume_threshold: 0.6", "listener_silence_timeout: 0.7", "interruptible: true".
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
flask[async]==3.0.3
flask-cors==4.0.1
nltk==3.8.1
gensim==4.3.3
sklearn==0.0
python-Levenshtein==0.25.1
fuzzywuzzy==0.18.0
Expand Down
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@
"wafl.connectors.clients",
"wafl.connectors.factories",
"wafl.connectors.remote",
"wafl.dataclasses",
"wafl.data_objects",
"wafl.events",
"wafl.extractors",
"wafl.handlers",
"wafl.inference",
"wafl.interface",
Expand All @@ -49,7 +48,6 @@
"flask[async]==3.0.3",
"flask-cors==4.0.1",
"nltk==3.8.1",
"gensim==4.3.3",
"sklearn==0.0",
"python-Levenshtein==0.25.1",
"fuzzywuzzy==0.18.0",
Expand Down
23 changes: 9 additions & 14 deletions tests/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,19 @@
"prompt_filename": "main.prompt",
"functions": "functions.py",
"max_recursion": 2,
"llm_model": {
"model_host": "localhost",
"model_port": 8080,
"frontend_port": 8090,
"backend": {
"host": "aragorn",
"port": 8080,
"token": "secret"
},
"generation_config": {
"temperature": 0.4
},
"listener_model": {
"model_host": "localhost",
"model_port": 8080,
"listener_hotword_logp": -8,
"listener_volume_threshold": 0.6,
"listener_silence_timeout": 0.7
},
"speaker_model": {
"model_host": "localhost",
"model_port": 8080
},
"text_embedding_model": {
"model_host": "localhost",
"model_port": 8080
"listener_silence_timeout": 0.7,
"interruptible": true
}
}
4 changes: 3 additions & 1 deletion tests/main.prompt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ The rules that *must* be followed are:

Create a plausible dialogue based on the aforementioned summary and rules.
Do not repeat yourself. Be friendly but not too servile.
Follow the rules if present and they apply to the dialogue. Do not improvise if rules are present.
Follow the rules if present and they apply to the dialogue. Do not improvise if rules are present.
The user query might be incomplete or ambiguous or ungrammatical. The bot *must* ask for clarification if needed.
The bot only answers if the query is clear and unambiguous.
6 changes: 3 additions & 3 deletions tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
class TestConnection(TestCase):
def test__connection_to_generative_model_can_generate_text(self):
config = Configuration.load_local_config()
connector = RemoteLLMConnector(config.get_value("llm_model"))
connector = RemoteLLMConnector(config)
prediction = asyncio.run(
connector.predict(
PromptCreator.create_from_one_instruction(
Expand All @@ -25,7 +25,7 @@ def test__connection_to_generative_model_can_generate_text(self):

def test__connection_to_generative_model_can_generate_text_within_tags(self):
config = Configuration.load_local_config()
connector = RemoteLLMConnector(config.get_value("llm_model"))
connector = RemoteLLMConnector(config)
connector._num_prediction_tokens = 200
text = 'Generate a full paragraph based on this chapter title " The First Contact". The theme of the paragraph is space opera. Include the characters "Alberto" and "Maria". Write at least three sentences.'
prompt = f"""
Expand All @@ -43,7 +43,7 @@ def test__connection_to_generative_model_can_generate_text_within_tags(self):

def test__connection_to_generative_model_can_generate_a_python_list(self):
config = Configuration.load_local_config()
connector = RemoteLLMConnector(config.get_value("llm_model"))
connector = RemoteLLMConnector(config)
connector._num_prediction_tokens = 200
prompt = "Generate a Python list of 4 chapters names for a space opera book. The output needs to be a python list of strings: "
prediction = asyncio.run(
Expand Down
34 changes: 34 additions & 0 deletions tests/test_entailer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import asyncio
import os

from unittest import TestCase
from wafl.config import Configuration
from wafl.connectors.remote.remote_entailer_connector import RemoteEntailerConnector
from wafl.connectors.clients.entailer_client import EntailerClient

_path = os.path.dirname(__file__)


class TestConnection(TestCase):
def test__entailer_connector(self):
config = Configuration.load_local_config()
connector = RemoteEntailerConnector(config)
prediction = asyncio.run(
connector.predict(
"The first contact is a romance novel set in the middle ages.",
"The first contact is a science fiction novel about the first contact between humans and aliens.",
)
)
assert prediction["score"] < 0.5

def test__entailment_client(self):

config = Configuration.load_local_config()
client = EntailerClient(config)
prediction = asyncio.run(
client.get_entailment_score(
"The first contact is a romance novel set in the middle ages.",
"The first contact is a science fiction novel about the first contact between humans and aliens.",
)
)
assert prediction < 0.5
2 changes: 1 addition & 1 deletion tests/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from unittest import TestCase

from wafl.config import Configuration
from wafl.dataclasses.dataclasses import Query
from wafl.data_objects.dataclasses import Query
from wafl.knowledge.indexing_implementation import add_to_index, load_knowledge

_path = os.path.dirname(__file__)
Expand Down
16 changes: 11 additions & 5 deletions tests/test_speaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from unittest import TestCase

from wafl.config import Configuration
from wafl.speaker.fairseq_speaker import FairSeqSpeaker
from wafl.speaker.tts_speaker import TTSSpeaker
from wafl.speaker.soundfile_speaker import SoundFileSpeaker

_wafl_greetings = """
Expand All @@ -17,24 +17,30 @@
class TestSpeaker(TestCase):
def test_voice(self):
config = Configuration.load_local_config()
speaker = FairSeqSpeaker(config)
speaker = TTSSpeaker(config)
text = "Hello world"
asyncio.run(speaker.speak(text))

def test_long_text(self):
config = Configuration.load_local_config()
speaker = FairSeqSpeaker(config)
speaker = TTSSpeaker(config)
text = (
"Shall I compare you to a summer's day? Thou art more lovely and temperate."
)
asyncio.run(speaker.speak(text))

def test_number_pronunciation(self):
def test_number_pronunciation1(self):
config = Configuration.load_local_config()
speaker = FairSeqSpeaker(config)
speaker = TTSSpeaker(config)
text = "The time is 54 past 8"
asyncio.run(speaker.speak(text))

def test_number_pronunciation2(self):
config = Configuration.load_local_config()
speaker = TTSSpeaker(config)
text = "The time is 8 54"
asyncio.run(speaker.speak(text))

def test_on_sound(self):
speaker = SoundFileSpeaker()
speaker.speak(os.path.join(_path, "../wafl/sounds/activation.wav"))
Expand Down
4 changes: 2 additions & 2 deletions tests/test_voice.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@

rules:
- the user's name is Jane:
- write "I hear you"
- reply with "I hear you" and nothing else
""".strip()

_path = os.path.dirname(__file__)


class TestVoice(TestCase):
def test__activation(self):
interface = DummyInterface(to_utter=["computer", "my name is Jane"])
interface = DummyInterface(to_utter=["computer my name is Jane"])
config = Configuration.load_local_config()
config.set_value("rules", _wafl_example)
conversation_events = ConversationEvents(config=config, interface=interface)
Expand Down
40 changes: 39 additions & 1 deletion todo.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
* why do I need to re-initialise the retrievers after unpickling the knowledge?
* user prior text and response from failed substitutions between [] instead of just iteration number (line 89, dialogue_answerer.py)
* remove dead code
* re-fine-tune phi to get better performance

* delete rules and memory from discourse_answerer

* This is wrong - from wafl_ll
<|end|><|assistant|><|user|> Hi!<|end|><|assistant|>
The user is sandwiched between the assistant. It should be:
<|end|><|assistant|> Hi!<|end|><|user|>

/* make interruptible speech optional


* use entailment score to flag a rule for execution before the answer.
* get all model list from wafl_llm backend. Only specify the connection port and host in wafl

* the answer from the indexed files should be directed from a rule.
- facts and rules should live at the highest level of the retrieval


/* apply entailer to rule retrieval:
/ if more than one rule is retrieved, then the one
/ that is entailed by the query should be chosen



/* Add tqdm to indexing.
/* Make it index when wafl start first, not at the first use/login

/* The prior items with timestamps might not be necessary.
/ - Just implement a queue with a fixed size

* add entailer to wafl_llm


/* why do I need to re-initialise the retrievers after unpickling the knowledge?
- maybe you should save the retrievers in the knowledge object separately?
- It was gensim that was not serializable. Took it out

/* knowledge cache does not cache the rules or facts

Expand Down
Loading
Loading