|
| 1 | +# SDK Documentation |
| 2 | + |
| 3 | +For those chatbots with complex Finite State Machine (FSM) behaviours, you will probably want to run them on a separate process, that is what for the SDK is made for. Its primary function is to execute the FSM's computations (transition's conditions and states) by running Remote Procedure Call (RPC) server that listen to the back-end requests. |
| 4 | + |
| 5 | +## Usage |
| 6 | + |
| 7 | +### Simple example |
| 8 | + |
| 9 | +This is just a dummy example that displays the basic usage of the library. |
| 10 | + |
| 11 | +We are going to build the next FSM: |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +Import basic modules to build your first FMS: |
| 16 | + |
| 17 | +```python |
| 18 | +import os |
| 19 | +import random |
| 20 | +from chatfaq_sdk import ChatFAQSDK |
| 21 | +from chatfaq_sdk.fsm import FSMDefinition, State, Transition |
| 22 | +from chatfaq_sdk.conditions import Condition |
| 23 | +from chatfaq_sdk.layers import Text |
| 24 | +``` |
| 25 | + |
| 26 | +Declare the 3 possible states of our FSM: |
| 27 | + |
| 28 | +```python |
| 29 | +def send_greeting(ctx: dict): |
| 30 | + yield Text("Hello!") |
| 31 | + yield Text("How are you?", allow_feedback=False) |
| 32 | + |
| 33 | +greeting_state = State(name="Greeting", events=[send_greeting], initial=True) |
| 34 | + |
| 35 | + |
| 36 | +def send_answer(ctx: dict): |
| 37 | + last_payload = ctx["last_mml"]["stack"][0]["payload"] |
| 38 | + yield Text( |
| 39 | + f'My answer to your message: "{last_payload}" is: {random.randint(0, 999)}' |
| 40 | + ) |
| 41 | + yield Text(f"Tell me more") |
| 42 | + |
| 43 | +answering_state = State( |
| 44 | + name="Answering", |
| 45 | + events=[send_answer], |
| 46 | +) |
| 47 | + |
| 48 | + |
| 49 | +def send_goodbye(ctx: dict): |
| 50 | + yield Text("Byeeeeeeee!", allow_feedback=False) |
| 51 | + |
| 52 | +goodbye_state = State( |
| 53 | + name="Goodbye", |
| 54 | + events=[send_goodbye], |
| 55 | +) |
| 56 | + |
| 57 | +``` |
| 58 | + |
| 59 | +Declare the only computable condition for the transitions of our FSM: |
| 60 | + |
| 61 | +```python |
| 62 | +def is_saying_goodbye(ctx: dict): |
| 63 | + if ctx["last_mml"]["stack"][0]["payload"] == "goodbye": |
| 64 | + return Condition(1) |
| 65 | + return Condition(0) |
| 66 | +``` |
| 67 | + |
| 68 | +Now lets glue everything together: |
| 69 | + |
| 70 | +Declare our transitions |
| 71 | + |
| 72 | +```python |
| 73 | +any_to_goodbye = Transition(dest=goodbye_state, conditions=[is_saying_goodbye]) |
| 74 | + |
| 75 | +greeting_to_answer = Transition( |
| 76 | + source=greeting_state, |
| 77 | + dest=answering_state, |
| 78 | + unless=[is_saying_goodbye], |
| 79 | +) |
| 80 | +answer_to_answer = Transition( |
| 81 | + source=answering_state, dest=answering_state, unless=[is_saying_goodbye] |
| 82 | +) |
| 83 | +``` |
| 84 | + |
| 85 | +Build the final instance of our FSM: |
| 86 | + |
| 87 | +```python |
| 88 | +fsm_definition = FSMDefinition( |
| 89 | + states=[greeting_state, answering_state, goodbye_state], |
| 90 | + transitions=[greeting_to_answer, any_to_goodbye, answer_to_answer], |
| 91 | +) |
| 92 | +``` |
| 93 | + |
| 94 | +Finally, run the RPC server loop with the previously built FSM: |
| 95 | + |
| 96 | +```python |
| 97 | +import os |
| 98 | + |
| 99 | +sdk = ChatFAQSDK( |
| 100 | + chatfaq_retrieval_http="http://localhost:8000", |
| 101 | + chatfaq_ws="ws://localhost:8000", |
| 102 | + token=os.getenv("CHATFAQ_TOKEN"), |
| 103 | + fsm_name="my_first_fsm", |
| 104 | + fsm_definition=fsm_definition, |
| 105 | +) |
| 106 | +sdk.connect() |
| 107 | +``` |
| 108 | + |
| 109 | +### Model example |
| 110 | + |
| 111 | +All of that is great, but where is the large language model capabilities that ChatFAQ offers? |
| 112 | + |
| 113 | +What if we want to build a FSM that makes use of a Language Model? |
| 114 | + |
| 115 | +For that, you first need to [configure your model](../configuration/index.md). |
| 116 | + |
| 117 | +Once you have configured all the components of the model, you will just need to reference the name of your RAG Configuration inside a state of the FSM. |
| 118 | + |
| 119 | +For example, if you have a RAG Configuration named `my_rag_config`, you can use it inside a state like this: |
| 120 | + |
| 121 | +```python |
| 122 | +from chatfaq_sdk.fsm import FSMDefinition, State, Transition |
| 123 | +from chatfaq_sdk.layers import LMGeneratedText, Text |
| 124 | + |
| 125 | + |
| 126 | +def send_greeting(ctx: dict): |
| 127 | + yield Text("How can we help you?", allow_feedback=False) |
| 128 | + |
| 129 | + |
| 130 | +def send_answer(ctx: dict): |
| 131 | + last_payload = ctx["last_mml"]["stack"][0]["payload"] |
| 132 | + yield LMGeneratedText(last_payload, "my_rag_config") |
| 133 | + |
| 134 | +greeting_state = State(name="Greeting", events=[send_greeting], initial=True) |
| 135 | + |
| 136 | +answering_state = State( |
| 137 | + name="Answering", |
| 138 | + events=[send_answer], |
| 139 | +) |
| 140 | + |
| 141 | +_to_answer = Transition( |
| 142 | + dest=answering_state, |
| 143 | +) |
| 144 | + |
| 145 | +fsm_definition = FSMDefinition( |
| 146 | + states=[greeting_state, answering_state], |
| 147 | + transitions=[_to_answer] |
| 148 | +) |
| 149 | +``` |
| 150 | + |
| 151 | +For the sake of completeness, here is the diagram of this FSM: |
| 152 | + |
| 153 | + |
0 commit comments