mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-18 20:17:50 +00:00
enhanced version
This commit is contained in:
parent
fff7d93bb2
commit
a40d67e737
495
docs/bindings/bindings_documentation.md
Normal file
495
docs/bindings/bindings_documentation.md
Normal file
@ -0,0 +1,495 @@
|
||||
I'll create a comprehensive guide on how to build a LoLLMs binding.
|
||||
|
||||
# Building a LoLLMs Binding - Developer Guide
|
||||
|
||||
## Introduction
|
||||
LoLLMs (Lord of Large Language Models) is a framework for interfacing with various language models. A binding is a connector that allows LoLLMs to interact with a specific model or API.
|
||||
|
||||
## Table of Contents
|
||||
1. Basic Structure
|
||||
2. Essential Components
|
||||
3. Binding Types
|
||||
4. Step-by-Step Guide
|
||||
5. Advanced Features
|
||||
6. Best Practices
|
||||
|
||||
## 1. Basic Structure
|
||||
|
||||
A LoLLMs binding consists of the following files:
|
||||
```
|
||||
binding_name/
|
||||
├── __init__.py
|
||||
├── binding.py
|
||||
├── config.yaml
|
||||
├── logo.png
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 2. Essential Components
|
||||
|
||||
### 2.1 Base Class
|
||||
All bindings must inherit from `LLMBinding`:
|
||||
|
||||
```python
|
||||
from lollms.binding import LLMBinding, LOLLMSConfig, BindingType
|
||||
from lollms.paths import LollmsPaths
|
||||
from lollms.config import BaseConfig, TypedConfig, ConfigTemplate, InstallOption
|
||||
|
||||
class YourBinding(LLMBinding):
|
||||
def __init__(self,
|
||||
config: LOLLMSConfig,
|
||||
lollms_paths: LollmsPaths = None,
|
||||
installation_option:InstallOption=InstallOption.INSTALL_IF_NECESSARY,
|
||||
lollmsCom=None) -> None:
|
||||
# Your initialization code
|
||||
```
|
||||
|
||||
### 2.2 Configuration
|
||||
Define your binding's configuration using TypedConfig:
|
||||
|
||||
```python
|
||||
binding_config = TypedConfig(
|
||||
ConfigTemplate([
|
||||
{"name":"api_key","type":"str","value":"", "help":"API key"},
|
||||
{"name":"temperature","type":"float","value":0.7, "min":0.0, "max":1.0},
|
||||
# Add more configuration parameters
|
||||
]),
|
||||
BaseConfig(config={})
|
||||
)
|
||||
```
|
||||
|
||||
## 3. Binding Types
|
||||
LoLLMs supports different binding types:
|
||||
```python
|
||||
class BindingType:
|
||||
TEXT = "text" # Text only
|
||||
TEXT_IMAGE = "text_image" # Text + image input
|
||||
MULTIMODAL = "multimodal" # Multiple input/output modalities
|
||||
```
|
||||
|
||||
## 4. Step-by-Step Guide
|
||||
|
||||
### 4.1 Create Basic Structure
|
||||
```python
|
||||
class YourBinding(LLMBinding):
|
||||
def __init__(self, config, lollms_paths=None, installation_option=InstallOption.INSTALL_IF_NECESSARY, lollmsCom=None):
|
||||
binding_config = TypedConfig(
|
||||
ConfigTemplate([
|
||||
# Your config parameters
|
||||
]),
|
||||
BaseConfig(config={})
|
||||
)
|
||||
|
||||
super().__init__(
|
||||
Path(__file__).parent,
|
||||
lollms_paths,
|
||||
config,
|
||||
binding_config,
|
||||
installation_option,
|
||||
supported_file_extensions=[''],
|
||||
lollmsCom=lollmsCom
|
||||
)
|
||||
```
|
||||
|
||||
### 4.2 Implement Required Methods
|
||||
|
||||
```python
|
||||
def build_model(self, model_name=None):
|
||||
"""Build or initialize the model"""
|
||||
super().build_model(model_name)
|
||||
# Your model initialization code
|
||||
return self
|
||||
|
||||
def generate(self,
|
||||
prompt: str,
|
||||
n_predict: int = 128,
|
||||
callback: Callable[[str], None] = None,
|
||||
verbose: bool = False,
|
||||
**gpt_params) -> str:
|
||||
"""Generate text from prompt"""
|
||||
# Your generation code
|
||||
|
||||
def tokenize(self, prompt:str):
|
||||
"""Tokenize text"""
|
||||
# Your tokenization code
|
||||
|
||||
def detokenize(self, tokens_list:list):
|
||||
"""Detokenize tokens"""
|
||||
# Your detokenization code
|
||||
|
||||
def list_models(self):
|
||||
"""List available models"""
|
||||
# Return list of model names
|
||||
|
||||
def get_available_models(self, app:LoLLMsCom=None):
|
||||
"""Get detailed model information"""
|
||||
# Return list of model details
|
||||
```
|
||||
|
||||
### 4.3 Installation Support
|
||||
```python
|
||||
def install(self):
|
||||
"""Install required packages"""
|
||||
super().install()
|
||||
PackageManager.install_package("your-required-package")
|
||||
```
|
||||
|
||||
## 5. Advanced Features
|
||||
|
||||
### 5.1 Image Support
|
||||
For bindings that support images:
|
||||
|
||||
```python
|
||||
def generate_with_images(self,
|
||||
prompt:str,
|
||||
images:list=[],
|
||||
n_predict: int = 128,
|
||||
callback: Callable[[str, int, dict], bool] = None,
|
||||
verbose: bool = False,
|
||||
**gpt_params):
|
||||
"""Generate text from prompt and images"""
|
||||
# Your image processing code
|
||||
```
|
||||
|
||||
### 5.2 Embedding Support
|
||||
For models that support embeddings:
|
||||
|
||||
```python
|
||||
def embed(self, text):
|
||||
"""Compute text embedding"""
|
||||
# Your embedding code
|
||||
return embedding_vector
|
||||
```
|
||||
|
||||
## 6. Best Practices
|
||||
|
||||
### 6.1 Error Handling
|
||||
Always implement proper error handling:
|
||||
|
||||
```python
|
||||
def generate(self, prompt, **kwargs):
|
||||
try:
|
||||
# Your generation code
|
||||
except Exception as ex:
|
||||
trace_exception(ex)
|
||||
self.error(ex)
|
||||
return ""
|
||||
```
|
||||
|
||||
### 6.2 Configuration Validation
|
||||
Validate configuration in settings_updated:
|
||||
|
||||
```python
|
||||
def settings_updated(self):
|
||||
if not self.binding_config.api_key:
|
||||
self.error("API key not set!")
|
||||
else:
|
||||
self.build_model()
|
||||
```
|
||||
|
||||
### 6.3 Documentation
|
||||
Always include:
|
||||
- README.md with usage instructions
|
||||
- Docstrings for methods
|
||||
- Configuration parameter descriptions
|
||||
- Requirements and dependencies
|
||||
|
||||
### 6.4 Status Updates
|
||||
Use provided methods for status updates:
|
||||
```python
|
||||
self.info("Information message")
|
||||
self.warning("Warning message")
|
||||
self.error("Error message")
|
||||
self.success("Success message")
|
||||
```
|
||||
|
||||
## Example config.yaml
|
||||
```yaml
|
||||
name: YourBinding
|
||||
author: Your Name
|
||||
version: 1.0.0
|
||||
description: Description of your binding
|
||||
url: https://github.com/yourusername/your-binding
|
||||
license: Apache 2.0
|
||||
```
|
||||
|
||||
I'll add a detailed section about callbacks in LoLLMs bindings.
|
||||
|
||||
# Callbacks in LoLLMs Bindings
|
||||
|
||||
## Introduction
|
||||
Callbacks are crucial in LoLLMs as they enable streaming text generation, allowing the UI to update in real-time and providing control over the generation process.
|
||||
|
||||
## Callback Types
|
||||
|
||||
```python
|
||||
from lollms.types import MSG_OPERATION_TYPE
|
||||
|
||||
|
||||
class MSG_OPERATION_TYPE(Enum):
|
||||
# Conditionning
|
||||
MSG_OPERATION_TYPE_ADD_CHUNK = 0 # Add a chunk to the current message
|
||||
MSG_OPERATION_TYPE_SET_CONTENT = 1 # sets the content of current message
|
||||
MSG_OPERATION_TYPE_SET_CONTENT_INVISIBLE_TO_AI = 2 # sets the content of current message as invisible to ai
|
||||
MSG_OPERATION_TYPE_SET_CONTENT_INVISIBLE_TO_USER = 3 # sets the content of current message as invisible to user
|
||||
# Informations
|
||||
MSG_OPERATION_TYPE_EXCEPTION = 4 # An exception occured
|
||||
MSG_OPERATION_TYPE_WARNING = 5 # A warning occured
|
||||
MSG_OPERATION_TYPE_INFO = 6 # An information to be shown to user
|
||||
|
||||
# Steps
|
||||
MSG_OPERATION_TYPE_STEP = 7 # An instant step (a step that doesn't need time to be executed)
|
||||
MSG_OPERATION_TYPE_STEP_START = 8 # A step has started (the text contains an explanation of the step done by he personality)
|
||||
MSG_OPERATION_TYPE_STEP_PROGRESS = 9 # The progress value (the text contains a percentage and can be parsed by the reception)
|
||||
MSG_OPERATION_TYPE_STEP_END_SUCCESS = 10# A step has been done (the text contains an explanation of the step done by he personality)
|
||||
MSG_OPERATION_TYPE_STEP_END_FAILURE = 11# A step has been done (the text contains an explanation of the step done by he personality)
|
||||
|
||||
#Extra
|
||||
MSG_OPERATION_TYPE_JSON_INFOS = 12# A JSON output that is useful for summarizing the process of generation used by personalities like chain of thoughts and tree of thooughts
|
||||
MSG_OPERATION_TYPE_REF = 13# References (in form of [text](path))
|
||||
MSG_OPERATION_TYPE_CODE = 14# A javascript code to execute
|
||||
MSG_OPERATION_TYPE_UI = 15# A vue.js component to show (we need to build some and parse the text to show it)
|
||||
|
||||
#Commands
|
||||
MSG_OPERATION_TYPE_NEW_MESSAGE = 16# A new message
|
||||
MSG_OPERATION_TYPE_FINISHED_MESSAGE = 17# End of current message
|
||||
```
|
||||
|
||||
## Implementation Examples
|
||||
|
||||
### 1. Basic Callback Usage
|
||||
|
||||
```python
|
||||
def generate(self,
|
||||
prompt: str,
|
||||
n_predict: int = 128,
|
||||
callback: Callable[[str, MSG_OPERATION_TYPE], bool] = None,
|
||||
verbose: bool = False,
|
||||
**gpt_params) -> str:
|
||||
"""
|
||||
Generate text with callback support
|
||||
|
||||
Args:
|
||||
prompt: Input text
|
||||
n_predict: Max tokens to generate
|
||||
callback: Function called for each generated chunk
|
||||
verbose: Enable verbose output
|
||||
"""
|
||||
output = ""
|
||||
try:
|
||||
# Example streaming response
|
||||
for chunk in model.stream_generate(prompt):
|
||||
if callback is not None:
|
||||
# Call callback with chunk and operation type
|
||||
# If callback returns False, stop generation
|
||||
if not callback(chunk, MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK):
|
||||
break
|
||||
output += chunk
|
||||
|
||||
except Exception as ex:
|
||||
trace_exception(ex)
|
||||
self.error(ex)
|
||||
|
||||
return output
|
||||
```
|
||||
|
||||
### 2. Advanced Callback Usage
|
||||
|
||||
```python
|
||||
def generate_with_images(self,
|
||||
prompt:str,
|
||||
images:list=[],
|
||||
n_predict: int = 128,
|
||||
callback: Callable[[str, MSG_OPERATION_TYPE, dict], bool] = None,
|
||||
verbose: bool = False,
|
||||
**gpt_params):
|
||||
"""Generate text with images and advanced callback usage"""
|
||||
|
||||
output = ""
|
||||
try:
|
||||
# Process response stream
|
||||
for chunk in model.stream_response():
|
||||
# Add new chunk
|
||||
if chunk.type == 'text':
|
||||
if callback is not None:
|
||||
# Send chunk with metadata
|
||||
metadata = {
|
||||
'token_count': len(self.tokenize(chunk.text)),
|
||||
'finish_reason': chunk.finish_reason
|
||||
}
|
||||
if not callback(chunk.text,
|
||||
MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK,
|
||||
metadata):
|
||||
break
|
||||
output += chunk.text
|
||||
|
||||
# Replace last chunk (e.g., for word corrections)
|
||||
elif chunk.type == 'correction':
|
||||
if callback is not None:
|
||||
if not callback(chunk.text,
|
||||
MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_REPLACE_LAST):
|
||||
break
|
||||
output = output[:-len(chunk.previous)] + chunk.text
|
||||
|
||||
# Add new line
|
||||
elif chunk.type == 'newline':
|
||||
if callback is not None:
|
||||
if not callback("\n",
|
||||
MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_NEW_LINE):
|
||||
break
|
||||
output += "\n"
|
||||
|
||||
except Exception as ex:
|
||||
trace_exception(ex)
|
||||
self.error(ex)
|
||||
|
||||
return output
|
||||
```
|
||||
|
||||
### 3. Callback with Progress Updates
|
||||
|
||||
```python
|
||||
def generate(self, prompt: str, n_predict: int = 128, callback=None, **kwargs):
|
||||
output = ""
|
||||
tokens_generated = 0
|
||||
|
||||
try:
|
||||
for chunk in model.stream_generate(prompt):
|
||||
tokens_generated += len(self.tokenize(chunk))
|
||||
|
||||
if callback is not None:
|
||||
# Include progress information
|
||||
metadata = {
|
||||
'progress': tokens_generated / n_predict,
|
||||
'tokens_generated': tokens_generated,
|
||||
'max_tokens': n_predict
|
||||
}
|
||||
|
||||
if not callback(chunk,
|
||||
MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK,
|
||||
metadata):
|
||||
break
|
||||
|
||||
output += chunk
|
||||
|
||||
# Check token limit
|
||||
if tokens_generated >= n_predict:
|
||||
break
|
||||
|
||||
except Exception as ex:
|
||||
trace_exception(ex)
|
||||
self.error(ex)
|
||||
|
||||
return output
|
||||
```
|
||||
|
||||
## Best Practices for Callbacks
|
||||
|
||||
1. **Always Check Callback Return Value**
|
||||
```python
|
||||
if callback is not None:
|
||||
if not callback(chunk, MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK):
|
||||
break # Stop generation if callback returns False
|
||||
```
|
||||
|
||||
2. **Handle Different Operation Types**
|
||||
```python
|
||||
# Add new content
|
||||
callback(chunk, MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK)
|
||||
|
||||
# Replace last chunk
|
||||
callback(corrected_text, MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_REPLACE_LAST)
|
||||
|
||||
# Add new line
|
||||
callback("\n", MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_NEW_LINE)
|
||||
```
|
||||
|
||||
3. **Include Useful Metadata**
|
||||
```python
|
||||
metadata = {
|
||||
'progress': current_tokens / max_tokens,
|
||||
'temperature': temperature,
|
||||
'token_count': token_count,
|
||||
'finish_reason': finish_reason
|
||||
}
|
||||
callback(chunk, operation_type, metadata)
|
||||
```
|
||||
|
||||
4. **Error Handling in Callbacks**
|
||||
```python
|
||||
try:
|
||||
if callback is not None:
|
||||
if not callback(chunk, MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK):
|
||||
break
|
||||
except Exception as ex:
|
||||
self.error(f"Callback error: {ex}")
|
||||
# Continue or break based on your needs
|
||||
```
|
||||
|
||||
5. **Respect Token Limits**
|
||||
```python
|
||||
token_count = len(self.tokenize(output))
|
||||
if token_count >= n_predict:
|
||||
if callback is not None:
|
||||
callback("", MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK,
|
||||
{'finish_reason': 'length'})
|
||||
break
|
||||
```
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. **Progress Display**
|
||||
```python
|
||||
def progress_callback(chunk, op_type, metadata=None):
|
||||
if metadata and 'progress' in metadata:
|
||||
print(f"Progress: {metadata['progress']*100:.2f}%")
|
||||
return True
|
||||
```
|
||||
|
||||
2. **Token Counting**
|
||||
```python
|
||||
def token_callback(chunk, op_type, metadata=None):
|
||||
if metadata and 'token_count' in metadata:
|
||||
print(f"Tokens generated: {metadata['token_count']}")
|
||||
return True
|
||||
```
|
||||
|
||||
3. **UI Updates**
|
||||
```python
|
||||
def ui_callback(chunk, op_type, metadata=None):
|
||||
if op_type == MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_ADD_CHUNK:
|
||||
update_ui_text(chunk)
|
||||
elif op_type == MSG_OPERATION_TYPE.MSG_OPERATION_TYPE_NEW_LINE:
|
||||
update_ui_newline()
|
||||
return True
|
||||
```
|
||||
|
||||
Remember that callbacks are essential for:
|
||||
- Real-time text streaming
|
||||
- Progress monitoring
|
||||
- User interaction
|
||||
- Generation control
|
||||
- UI updates
|
||||
|
||||
Using callbacks effectively makes your binding more interactive and user-friendly.
|
||||
|
||||
## Conclusion
|
||||
Building a LoLLMs binding requires:
|
||||
1. Implementing the base interface
|
||||
2. Proper configuration management
|
||||
3. Error handling
|
||||
4. Documentation
|
||||
5. Following best practices
|
||||
|
||||
For more examples, check the official LoLLMs bindings repository.
|
||||
|
||||
Remember to test your binding thoroughly and maintain compatibility with the LoLLMs framework's conventions and interfaces.
|
||||
|
||||
## Support
|
||||
For help or questions about binding development:
|
||||
- Visit the LoLLMs GitHub repository
|
||||
- Join the community discussion
|
||||
- Check existing bindings for examples
|
||||
|
||||
Happy binding development!
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 6c07bf0b1d84e5cb836b9b04f1ad802ba02f697d
|
||||
Subproject commit 44516ab4452f31a9b5c7b678f2baaec45e99943c
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
web/dist/index.html
vendored
4
web/dist/index.html
vendored
@ -6,8 +6,8 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LoLLMS WebUI</title>
|
||||
<script type="module" crossorigin src="/assets/index-Do2d1uFW.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-D-SRf9s3.css">
|
||||
<script type="module" crossorigin src="/assets/index-D5M9NMgK.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DOUboDIx.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
:class="selected ? 'discussion-hilighted min-w-[14rem] max-w-[14rem]' : 'discussion min-w-[14rem] max-w-[14rem]'"
|
||||
class="m-1 py-2 flex flex-row sm:flex-row flex-wrap flex-shrink-0 items-center rounded-md duration-75 group cursor-pointer relative"
|
||||
class="m-1 py-2 flex flex-row sm:flex-row flex-wrap flex-shrink-0 items-center rounded-md duration-75 cursor-pointer relative"
|
||||
:id="'dis-' + id"
|
||||
@click.stop="selectEvent()"
|
||||
>
|
||||
@ -62,7 +62,7 @@
|
||||
</div>
|
||||
<!-- CONTROL BUTTONS AS SLIDING FLOATING MENU -->
|
||||
<div
|
||||
class="absolute top-0 right-0 h-full flex items-center"
|
||||
class="absolute top-0 right-0 h-full flex items-center group"
|
||||
>
|
||||
<div
|
||||
class="flex gap-2 items-center bg-white dark:bg-gray-800 p-2 rounded-l-md shadow-md transform translate-x-full group-hover:translate-x-0 transition-transform duration-300"
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 038c6f81498b278e189d61feb4835d96cd4ed900
|
||||
Subproject commit 9d7182f972199b99022372937486ae771774f910
|
@ -1 +1 @@
|
||||
Subproject commit f69d523ed29f2765653d25e36a21c7d4f2ef53bb
|
||||
Subproject commit 775191a34df687db73f7e70587de778a4de2e04b
|
Loading…
Reference in New Issue
Block a user