|
| 1 | +# 🧠🔗 Synalinks |
| 2 | + |
| 3 | +## What is Synalinks? |
| 4 | + |
| 5 | +Synalinks is an open-source framework that makes it easy to create, evaluate, train, and deploy industry-standard Language Models (LMs) applications. Synalinks follows the principle of *progressive disclosure of complexity*: meaning that simple workflows should be quick and easy, while arbitrarily advanced ones should be possible via a clear path that builds upon what you've already learned. |
| 6 | + |
| 7 | +Synalinks is a *fork of Keras 3* adapted for neuro-symbolic systems and in-context reinforcement learning, an ensemble of techniques that enhance the LMs predictions and accuracy without changing the weights of the model. We also provide techniques and optimizers to automatically collect data in order to train and fine-tune your own LMs. The goal of Synalinks is to facilitate the rapid setup of simple applications while providing the flexibility for researchers and advanced users to develop sophisticated systems. |
| 8 | + |
| 9 | +## Who is Synalinks for? |
| 10 | + |
| 11 | +Synalinks is designed for a diverse range of users, from professionals and AI researchers to students, independent developers, and hobbyists. It is suitable for anyone who wants to learn about AI by building/composing blocks or build solid foundations for enterprise-grade products. While a background in Machine Learning and Deep Learning can be advantageous — as Synalinks leverages design patterns from Keras, one of the most user-friendly and popular Deep Learning frameworks — it is not a prerequisite. Synalinks is designed to be accessible to anyone with basic programming skills in Python, making it a versatile and inclusive platform for AI development. |
| 12 | + |
| 13 | +## Why use Synalinks? |
| 14 | + |
| 15 | +Developping a successful LM application in a profesional context, beyond stateless chatbots, is difficult and typically include: |
| 16 | + |
| 17 | +- Building optimized prompts with examples/hints at each step |
| 18 | +- Pipelines that change over time |
| 19 | +- Assessing the performance of your application |
| 20 | +- Configuring Language Models |
| 21 | +- Building data extraction pipelines |
| 22 | +- Documenting your ML workflows |
| 23 | +- Using advanced in-context RL techniques and symbolic systems |
| 24 | +- Traning, evaluating and versioning the prompts/pipelines |
| 25 | +- Deploying REST APIs |
| 26 | + |
| 27 | +Synalinks can help you simplify these tasks by leveraging decade old practices in Deep Learning frameworks. We provide a comprehensive suite of tools and features designed to streamline the development process, making it easier to create, evaluate, train, document and deploy robust neuro-symbolic LMs applications. |
| 28 | + |
| 29 | +### Install |
| 30 | + |
| 31 | +```shell |
| 32 | +pip install synalinks |
| 33 | +``` |
| 34 | + |
| 35 | +## Programming your application: 3 ways |
| 36 | + |
| 37 | +### Using the `Functional` API |
| 38 | + |
| 39 | +You start from `Input`, you chain modules calls to specify the model's forward pass, and finally, you create your model from inputs and outputs: |
| 40 | + |
| 41 | +```python |
| 42 | +import synalinks |
| 43 | + |
| 44 | +class Query(synalinks.DataModel): |
| 45 | + query: str |
| 46 | + |
| 47 | +class AnswerWithRationale(synalinks.DataModel): |
| 48 | + rationale: str |
| 49 | + answer: str |
| 50 | + |
| 51 | +language_model = synalinks.LanguageModel(model="ollama/mistral") |
| 52 | + |
| 53 | +x0 = synalinks.Input(data_model=Query) |
| 54 | +x1 = synalinks.Generator( |
| 55 | + data_model=AnswerWithRationale, |
| 56 | + language_model=language_model |
| 57 | +)(x0) |
| 58 | + |
| 59 | +program = synalinks.Program( |
| 60 | + inputs=x0, |
| 61 | + outputs=x1, |
| 62 | + name="chain_of_thought", |
| 63 | + description="Usefull to answer in a step by step manner.", |
| 64 | +) |
| 65 | +``` |
| 66 | + |
| 67 | +### Subclassing the `Program` class |
| 68 | + |
| 69 | +In that case, you should define your modules in `__init__()` and you should implement the model's forward pass in `call()`. |
| 70 | + |
| 71 | +**Note:** you can optionaly have a `training` argument (boolean), which you can use to specify a different behavior in training and inference. |
| 72 | + |
| 73 | +```python |
| 74 | +import synalinks |
| 75 | + |
| 76 | +class Query(synalinks.DataModel): |
| 77 | + query: str |
| 78 | + |
| 79 | +class AnswerWithRationale(synalinks.DataModel): |
| 80 | + rationale: str |
| 81 | + answer: str |
| 82 | + |
| 83 | +class ChainOfThought(synalinks.Program): |
| 84 | + """Usefull to answer in a step by step manner. |
| 85 | + |
| 86 | + The first line of the docstring is provided as description |
| 87 | + for the program if not provided in the `super().__init__()`. |
| 88 | + In a similar way the name is automatically infered based on |
| 89 | + the class name if not provided. |
| 90 | + """ |
| 91 | + |
| 92 | + def __init__(self, language_model=None): |
| 93 | + super().__init__() |
| 94 | + self.answer = synalinks.Generator( |
| 95 | + data_model=AnswerWithRationale, |
| 96 | + language_model=language_model |
| 97 | + ) |
| 98 | + |
| 99 | + def call(self, inputs): |
| 100 | + x = self.answer(inputs) |
| 101 | + return x |
| 102 | + |
| 103 | +program = ChainOfThought(language_model=language_model) |
| 104 | +``` |
| 105 | + |
| 106 | +### Using the `Sequential` API |
| 107 | + |
| 108 | +In addition, `Sequential` is a special case of program where the program |
| 109 | +is purely a stack of single-input, single-output modules. |
| 110 | + |
| 111 | +```python |
| 112 | +import synalinks |
| 113 | + |
| 114 | +class Query(synalinks.DataModel): |
| 115 | + query: str |
| 116 | + |
| 117 | +class AnswerWithRationale(synalinks.DataModel): |
| 118 | + rationale: str |
| 119 | + answer: str |
| 120 | + |
| 121 | +language_model = synalinks.LanguageModel(model="ollama/mistral") |
| 122 | + |
| 123 | +program = synalinks.Sequential( |
| 124 | + [ |
| 125 | + synalinks.Input( |
| 126 | + data_model=Query, |
| 127 | + ), |
| 128 | + synalinks.Generator( |
| 129 | + data_model=AnswerWithRationale, |
| 130 | + language_model=language_model, |
| 131 | + ), |
| 132 | + ], |
| 133 | + name="chain_of_thought", |
| 134 | + description="Usefull to answer in a step by step manner.", |
| 135 | +) |
| 136 | +``` |
| 137 | + |
| 138 | +## Getting summary of your program |
| 139 | + |
| 140 | +To print a tabular summary of your program: |
| 141 | + |
| 142 | +```python |
| 143 | +program.summary() |
| 144 | +``` |
| 145 | + |
| 146 | +Or a plot (usefull to document your system): |
| 147 | + |
| 148 | +```python |
| 149 | +synalinks.utils.plot_program( |
| 150 | + program, |
| 151 | + show_trainable=True, |
| 152 | + show_schema=True, |
| 153 | +) |
| 154 | +``` |
| 155 | + |
| 156 | +## Running your program |
| 157 | + |
| 158 | +To run your program use the following: |
| 159 | + |
| 160 | +```python |
| 161 | +result = program(Query(query="What is the French city of aerospace?")) |
| 162 | + |
| 163 | +print(result) |
| 164 | +``` |
| 165 | + |
| 166 | +## Training your program |
| 167 | + |
| 168 | +```python |
| 169 | +(x_train, y_train), (x_test, y_test) = synalinks.datasets.gsm8k.load_data() |
| 170 | + |
| 171 | +program.compile( |
| 172 | + reward=synalinks.rewards.ExactMatch(in_mask=["answer"]), |
| 173 | + optimizer=synalinks.optimizers.RandomFewShot() |
| 174 | +) |
| 175 | + |
| 176 | +batch_size=32 |
| 177 | +epochs=2 |
| 178 | + |
| 179 | +program.fit( |
| 180 | + x_train, |
| 181 | + y_train, |
| 182 | + batch_size=batch_size, |
| 183 | + epochs=epochs, |
| 184 | + validation_split=0.15, |
| 185 | +) |
| 186 | + |
| 187 | +metrics = program.evaluate(x_test, y_test, verbose=0, return_dict=True) |
| 188 | +``` |
| 189 | + |
| 190 | +### Learn more |
| 191 | + |
| 192 | +You can learn more on how to create your RAG/Graph-RAG or Agentic applications by reading our [documentation](docs/) or [notebooks](notebooks/). If you have questions about our vision or approach, the [FAQ]() might help you. |
| 193 | + |
| 194 | +### Contributions |
| 195 | + |
| 196 | +Contributions are welcome, either for the implementation of additional modules, metrics, optimizers or for database integrations. |
| 197 | +For more information, or help for implementing your ideas (or ones from a paper), please join our discord. |
| 198 | + |
| 199 | +Beware that every additional metric/module/optimizer should be approved by the core team, we want to keep the library minimal and clean as possible to avoid an uncontrolled growth leading to bad software practices like in most current leading LM frameworks. |
| 200 | + |
| 201 | +### Community |
| 202 | + |
| 203 | +[Discord]() |
| 204 | + |
| 205 | +Join our community to learn more about neuro-symbolic systems and the future of AI. We welcome the participation of people from very different backgrounds or education levels. |
| 206 | + |
| 207 | +### Credit |
| 208 | + |
| 209 | +Synalinks would not be possible without the great work of the following open-source projects: |
| 210 | + |
| 211 | +- [Keras](https://keras.io/) for the graph-based computation backbone, API and overall code, design and philosophy |
| 212 | +- [DSPy](https://dspy.ai/) for the modules/optimizers inspiration |
| 213 | +- [AdalFlow](https://github.com/SylphAI-Inc/AdalFlow) for the the use of jinja2 templates in a self-contained prompt |
| 214 | +- [Pydantic](https://docs.pydantic.dev/latest/) for the backend data layer |
0 commit comments