Skip to content

Commit

Permalink
Merge pull request #143 from fractalego/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
fractalego authored Dec 15, 2024
2 parents e646b01 + 16d7ee0 commit 9d468b2
Show file tree
Hide file tree
Showing 62 changed files with 623 additions and 349 deletions.
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

0 comments on commit 9d468b2

Please sign in to comment.