- 7 docs revised.
This commit is contained in:
parent
f44b81e396
commit
af865b87e7
16 changed files with 2084 additions and 1434 deletions
|
|
@ -88,11 +88,12 @@
|
||||||
- [Architecture Overview](./chapter-07-gbapp/architecture.md)
|
- [Architecture Overview](./chapter-07-gbapp/architecture.md)
|
||||||
- [Building from Source](./chapter-07-gbapp/building.md)
|
- [Building from Source](./chapter-07-gbapp/building.md)
|
||||||
- [Container Deployment (LXC)](./chapter-07-gbapp/containers.md)
|
- [Container Deployment (LXC)](./chapter-07-gbapp/containers.md)
|
||||||
|
- [Philosophy](./chapter-07-gbapp/philosophy.md)
|
||||||
|
- [Example gbapp](./chapter-07-gbapp/example-gbapp.md)
|
||||||
- [Module Structure](./chapter-07-gbapp/crates.md)
|
- [Module Structure](./chapter-07-gbapp/crates.md)
|
||||||
- [Service Layer](./chapter-07-gbapp/services.md)
|
- [Service Layer](./chapter-07-gbapp/services.md)
|
||||||
- [Creating Custom Keywords](./chapter-07-gbapp/custom-keywords.md)
|
- [Creating Custom Keywords](./chapter-07-gbapp/custom-keywords.md)
|
||||||
- [Adding Dependencies](./chapter-07-gbapp/dependencies.md)
|
- [Adding Dependencies](./chapter-07-gbapp/dependencies.md)
|
||||||
- [Prompt Manager](./chapter-07-gbapp/prompt-manager.md)
|
|
||||||
|
|
||||||
# Part VIII - Bot Configuration
|
# Part VIII - Bot Configuration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,251 +1,293 @@
|
||||||
# FIND
|
# FIND
|
||||||
|
|
||||||
**Search for specific data in storage or knowledge bases.** The FIND keyword performs targeted searches in bot memory, databases, or document collections to locate specific information.
|
Search and retrieve data from database tables using filter criteria.
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
|
|
||||||
```basic
|
```basic
|
||||||
result = FIND(pattern)
|
result = FIND "table_name", "filter_criteria"
|
||||||
result = FIND(pattern, location)
|
|
||||||
result = FIND(pattern, location, options)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
- `pattern` - Search pattern or query string
|
- `table_name` - The name of the database table to search
|
||||||
- `location` - Where to search (optional, defaults to current KB)
|
- `filter_criteria` - Filter expression in the format "field=value"
|
||||||
- `options` - Search options like case sensitivity, limit (optional)
|
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
FIND searches for data matching a pattern. Unlike semantic search with LLM, FIND does exact or pattern-based matching. Useful for structured data, IDs, specific values.
|
FIND searches database tables for records matching specified criteria. It returns an array of matching records that can be iterated over using FOR EACH loops.
|
||||||
|
|
||||||
## Search Locations
|
|
||||||
|
|
||||||
### Bot Memory
|
|
||||||
```basic
|
|
||||||
' Find in bot's permanent storage
|
|
||||||
user_data = FIND("user_*", "BOT_MEMORY")
|
|
||||||
' Returns all keys starting with "user_"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Session Variables
|
|
||||||
```basic
|
|
||||||
' Find in current session
|
|
||||||
form_fields = FIND("form_*", "SESSION")
|
|
||||||
' Returns all form-related variables
|
|
||||||
```
|
|
||||||
|
|
||||||
### Knowledge Base
|
|
||||||
```basic
|
|
||||||
' Find specific documents
|
|
||||||
policies = FIND("*.pdf", "policies")
|
|
||||||
' Returns all PDFs in policies collection
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database
|
|
||||||
```basic
|
|
||||||
' Find in database tables
|
|
||||||
orders = FIND("status:pending", "orders")
|
|
||||||
' Returns pending orders
|
|
||||||
```
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Basic Search
|
### Basic Search
|
||||||
```basic
|
```basic
|
||||||
' Find a specific user
|
' Find records with specific action
|
||||||
user = FIND("email:john@example.com")
|
items = FIND "gb.rob", "ACTION=EMUL"
|
||||||
|
|
||||||
if user
|
|
||||||
TALK "Found user: " + user.name
|
|
||||||
else
|
|
||||||
TALK "User not found"
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pattern Matching
|
|
||||||
```basic
|
|
||||||
' Find all items matching pattern
|
|
||||||
items = FIND("SKU-2024-*")
|
|
||||||
|
|
||||||
FOR EACH item IN items
|
FOR EACH item IN items
|
||||||
TALK item.name + ": " + item.price
|
TALK "Found: " + item.company
|
||||||
END
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multi-Criteria Search
|
### Single Field Filter
|
||||||
```basic
|
```basic
|
||||||
' Complex search with multiple conditions
|
' Find pending orders
|
||||||
results = FIND("type:invoice AND status:unpaid AND date>2024-01-01")
|
orders = FIND "orders", "status=pending"
|
||||||
|
|
||||||
total = 0
|
FOR EACH order IN orders
|
||||||
FOR EACH invoice IN results
|
TALK "Order #" + order.id + " is pending"
|
||||||
total = total + invoice.amount
|
NEXT
|
||||||
END
|
|
||||||
TALK "Total unpaid: $" + total
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Search with Options
|
### Working with Results
|
||||||
```basic
|
```basic
|
||||||
' Limited, case-insensitive search
|
' Find and process customer records
|
||||||
matches = FIND("john", "customers", {
|
customers = FIND "customers", "city=Seattle"
|
||||||
case_sensitive: false,
|
|
||||||
limit: 10,
|
FOR EACH customer IN customers
|
||||||
fields: ["name", "email"]
|
TALK customer.name + " from " + customer.address
|
||||||
})
|
|
||||||
|
' Access fields with dot notation
|
||||||
|
email = customer.email
|
||||||
|
phone = customer.phone
|
||||||
|
|
||||||
|
' Update related data
|
||||||
|
SET "contacts", "id=" + customer.id, "last_contacted=" + NOW()
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
## Return Values
|
## Return Value
|
||||||
|
|
||||||
FIND returns different types based on matches:
|
FIND returns an array of records from the specified table. Each record is an object with fields accessible via dot notation.
|
||||||
|
|
||||||
- **Single match** - Returns the item directly
|
- Returns empty array if no matches found
|
||||||
- **Multiple matches** - Returns array of items
|
- Returns array of matching records if successful
|
||||||
- **No matches** - Returns null or empty array
|
- Each record contains all columns from the table
|
||||||
- **Error** - Returns null with error in ERROR variable
|
|
||||||
|
## Field Access
|
||||||
|
|
||||||
|
Access fields in returned records using dot notation:
|
||||||
|
|
||||||
|
```basic
|
||||||
|
items = FIND "products", "category=electronics"
|
||||||
|
|
||||||
|
FOR EACH item IN items
|
||||||
|
' Access fields directly
|
||||||
|
TALK item.name
|
||||||
|
TALK item.price
|
||||||
|
TALK item.description
|
||||||
|
|
||||||
|
' Use null coalescing for optional fields
|
||||||
|
website = item.website ?? ""
|
||||||
|
|
||||||
|
' Check field existence
|
||||||
|
IF item.discount != "" THEN
|
||||||
|
TALK "On sale: " + item.discount + "% off"
|
||||||
|
END IF
|
||||||
|
NEXT
|
||||||
|
```
|
||||||
|
|
||||||
## Common Patterns
|
## Common Patterns
|
||||||
|
|
||||||
### Check Existence
|
### Process All Matching Records
|
||||||
```basic
|
```basic
|
||||||
exists = FIND("id:" + user_id)
|
tasks = FIND "tasks", "status=open"
|
||||||
if exists
|
|
||||||
TALK "User already registered"
|
FOR EACH task IN tasks
|
||||||
else
|
' Process each task
|
||||||
' Create new user
|
TALK "Processing task: " + task.title
|
||||||
end
|
|
||||||
|
' Update task status
|
||||||
|
SET "tasks", "id=" + task.id, "status=in_progress"
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
### Filter Results
|
### Check If Records Exist
|
||||||
```basic
|
```basic
|
||||||
all_products = FIND("*", "products")
|
users = FIND "users", "email=john@example.com"
|
||||||
in_stock = []
|
|
||||||
|
|
||||||
FOR EACH product IN all_products
|
IF LENGTH(users) > 0 THEN
|
||||||
if product.quantity > 0
|
TALK "User exists"
|
||||||
in_stock.append(product)
|
ELSE
|
||||||
end
|
TALK "User not found"
|
||||||
END
|
END IF
|
||||||
```
|
```
|
||||||
|
|
||||||
### Aggregate Data
|
### Data Enrichment
|
||||||
```basic
|
```basic
|
||||||
sales = FIND("date:" + TODAY(), "transactions")
|
companies = FIND "companies", "needs_update=true"
|
||||||
daily_total = 0
|
|
||||||
|
|
||||||
FOR EACH sale IN sales
|
FOR EACH company IN companies
|
||||||
daily_total = daily_total + sale.amount
|
' Get additional data
|
||||||
END
|
website = company.website ?? ""
|
||||||
|
|
||||||
TALK "Today's sales: $" + daily_total
|
IF website == "" THEN
|
||||||
|
' Look up website
|
||||||
|
website = WEBSITE OF company.name
|
||||||
|
|
||||||
|
' Update record
|
||||||
|
SET "companies", "id=" + company.id, "website=" + website
|
||||||
|
END IF
|
||||||
|
|
||||||
|
' Fetch and process website data
|
||||||
|
page = GET website
|
||||||
|
' Process page content...
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
### Search History
|
### Batch Processing with Delays
|
||||||
```basic
|
```basic
|
||||||
' Find previous conversations
|
emails = FIND "email_queue", "sent=false"
|
||||||
history = FIND("session:" + user_id, "messages", {
|
|
||||||
sort: "timestamp DESC",
|
|
||||||
limit: 50
|
|
||||||
})
|
|
||||||
|
|
||||||
TALK "Your last conversation:"
|
FOR EACH email IN emails
|
||||||
FOR EACH message IN history
|
' Send email
|
||||||
TALK message.timestamp + ": " + message.content
|
SEND MAIL email.to, email.subject, email.body
|
||||||
END
|
|
||||||
|
' Mark as sent
|
||||||
|
SET "email_queue", "id=" + email.id, "sent=true"
|
||||||
|
|
||||||
|
' Rate limiting
|
||||||
|
WAIT 1000
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance Tips
|
## Filter Expressions
|
||||||
|
|
||||||
|
The filter parameter uses simple equality expressions:
|
||||||
|
|
||||||
|
- `"field=value"` - Match exact value
|
||||||
|
- Multiple conditions must be handled in BASIC code after retrieval
|
||||||
|
|
||||||
### Use Specific Patterns
|
|
||||||
```basic
|
```basic
|
||||||
' Good - Specific pattern
|
' Get all records then filter in BASIC
|
||||||
orders = FIND("order_2024_01_*")
|
all_orders = FIND "orders", "status=active"
|
||||||
|
|
||||||
' Bad - Too broad
|
FOR EACH order IN all_orders
|
||||||
everything = FIND("*")
|
' Additional filtering in code
|
||||||
|
IF order.amount > 1000 AND order.priority == "high" THEN
|
||||||
|
' Process high-value orders
|
||||||
|
TALK "Priority order: " + order.id
|
||||||
|
END IF
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
### Limit Results
|
## Working with Different Data Types
|
||||||
```basic
|
|
||||||
' Get only what you need
|
|
||||||
recent = FIND("*", "logs", {limit: 100})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cache Repeated Searches
|
|
||||||
```basic
|
```basic
|
||||||
' Cache for session
|
products = FIND "products", "active=true"
|
||||||
if not cached_products
|
|
||||||
cached_products = FIND("*", "products")
|
FOR EACH product IN products
|
||||||
end
|
' String fields
|
||||||
' Use cached_products instead of searching again
|
name = product.name
|
||||||
|
|
||||||
|
' Numeric fields
|
||||||
|
price = product.price
|
||||||
|
quantity = product.quantity
|
||||||
|
|
||||||
|
' Date fields
|
||||||
|
created = product.created_at
|
||||||
|
|
||||||
|
' Boolean-like fields (stored as strings)
|
||||||
|
IF product.featured == "true" THEN
|
||||||
|
TALK "Featured: " + name
|
||||||
|
END IF
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
## Error Handling
|
## Error Handling
|
||||||
|
|
||||||
```basic
|
```basic
|
||||||
try
|
' Handle potential errors
|
||||||
results = FIND(user_query)
|
items = FIND "inventory", "warehouse=main"
|
||||||
if results
|
|
||||||
TALK "Found " + LENGTH(results) + " matches"
|
IF items == null THEN
|
||||||
else
|
TALK "Error accessing inventory data"
|
||||||
TALK "No results found"
|
ELSE IF LENGTH(items) == 0 THEN
|
||||||
end
|
TALK "No items found in main warehouse"
|
||||||
catch error
|
ELSE
|
||||||
TALK "Search failed. Please try again."
|
TALK "Found " + LENGTH(items) + " items"
|
||||||
LOG "FIND error: " + error
|
' Process items...
|
||||||
end
|
END IF
|
||||||
```
|
```
|
||||||
|
|
||||||
## Comparison with Other Keywords
|
## Performance Considerations
|
||||||
|
|
||||||
| Keyword | Purpose | Use When |
|
1. **Limit Results**: The system automatically limits to 10 results for safety
|
||||||
|---------|---------|----------|
|
2. **Use Specific Filters**: More specific filters reduce processing time
|
||||||
| FIND | Exact/pattern search | Looking for specific values |
|
3. **Avoid Full Table Scans**: Always provide a filter criterion
|
||||||
| LLM | Semantic search | Understanding meaning |
|
4. **Process in Batches**: For large datasets, process in chunks
|
||||||
| GET | Direct retrieval | Know exact key |
|
|
||||||
| USE KB | Activate knowledge | Need document context |
|
|
||||||
|
|
||||||
## Advanced Usage
|
|
||||||
|
|
||||||
### Dynamic Location
|
|
||||||
```basic
|
```basic
|
||||||
department = GET user.department
|
' Process records in batches
|
||||||
data = FIND("*", department + "_records")
|
batch = FIND "large_table", "processed=false"
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
FOR EACH record IN batch
|
||||||
|
' Process record
|
||||||
|
SET "large_table", "id=" + record.id, "processed=true"
|
||||||
|
|
||||||
|
count = count + 1
|
||||||
|
IF count >= 10 THEN
|
||||||
|
EXIT FOR ' Process max 10 at a time
|
||||||
|
END IF
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compound Searches
|
## Integration with Other Keywords
|
||||||
|
|
||||||
|
### With SET for Updates
|
||||||
```basic
|
```basic
|
||||||
' Find in multiple places
|
users = FIND "users", "newsletter=true"
|
||||||
local = FIND(query, "local_db")
|
|
||||||
remote = FIND(query, "remote_api")
|
FOR EACH user IN users
|
||||||
results = MERGE(local, remote)
|
' Update last_notified field
|
||||||
|
SET "users", "id=" + user.id, "last_notified=" + NOW()
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
### Conditional Fields
|
### With LLM for Processing
|
||||||
```basic
|
```basic
|
||||||
search_fields = ["name"]
|
articles = FIND "articles", "needs_summary=true"
|
||||||
if advanced_mode
|
|
||||||
search_fields.append(["email", "phone", "address"])
|
|
||||||
end
|
|
||||||
|
|
||||||
results = FIND(term, "contacts", {fields: search_fields})
|
FOR EACH article IN articles
|
||||||
|
summary = LLM "Summarize: " + article.content
|
||||||
|
SET "articles", "id=" + article.id, "summary=" + summary
|
||||||
|
NEXT
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### With CREATE SITE
|
||||||
|
```basic
|
||||||
|
companies = FIND "companies", "needs_site=true"
|
||||||
|
|
||||||
|
FOR EACH company IN companies
|
||||||
|
alias = LLM "Create URL alias for: " + company.name
|
||||||
|
CREATE SITE alias, "template", "Create site for " + company.name
|
||||||
|
SET "companies", "id=" + company.id, "site_url=" + alias
|
||||||
|
NEXT
|
||||||
|
```
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- Maximum 10 records returned per query (system limit)
|
||||||
|
- Filter supports simple equality only
|
||||||
|
- Complex queries require post-processing in BASIC
|
||||||
|
- Table must exist in the database
|
||||||
|
- User must have read permissions on the table
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
✅ **Be specific** - Use precise patterns to avoid large result sets
|
✅ **Always check results** - Verify FIND returned data before processing
|
||||||
✅ **Handle empty results** - Always check if FIND returned data
|
✅ **Use specific filters** - Reduce result set size with precise criteria
|
||||||
✅ **Use appropriate location** - Search where data actually lives
|
✅ **Handle empty results** - Check LENGTH before iterating
|
||||||
✅ **Limit when possible** - Don't retrieve more than needed
|
✅ **Update as you go** - Mark records as processed to avoid reprocessing
|
||||||
|
|
||||||
❌ **Don't search everything** - Avoid FIND("*") without limits
|
❌ **Don't assume order** - Results may not be sorted
|
||||||
❌ **Don't assume order** - Results may not be sorted unless specified
|
❌ **Don't ignore limits** - Remember the 10-record limit
|
||||||
❌ **Don't ignore errors** - Wrap in try/catch for production
|
❌ **Don't use without filter** - Always provide filter criteria
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [GET](./keyword-get.md) - Direct key retrieval
|
- [SET](./keyword-set.md) - Update database records
|
||||||
- [SET](./keyword-set.md) - Store data
|
- [GET](./keyword-get.md) - Retrieve single values
|
||||||
- [USE KB](./keyword-use-kb.md) - Semantic document search
|
- [FOR EACH](./keyword-for-each.md) - Iterate over results
|
||||||
- [LLM](./keyword-llm.md) - AI-powered search
|
- [LLM](./keyword-llm.md) - Process found data with AI
|
||||||
|
|
@ -242,15 +242,11 @@ END IF
|
||||||
|
|
||||||
### Authentication Failed
|
### Authentication Failed
|
||||||
|
|
||||||
```basic
|
Check SMTP configuration:
|
||||||
' Test SMTP connection
|
1. Verify credentials in `config.csv`
|
||||||
TEST_SMTP_CONNECTION()
|
2. Ensure SMTP server allows your connection
|
||||||
IF CONNECTION_OK THEN
|
3. Check if port 587/465 is open
|
||||||
TALK "SMTP connection successful"
|
4. Verify TLS/SSL settings match server requirements
|
||||||
ELSE
|
|
||||||
TALK "Check email-user and email-pass in config.csv"
|
|
||||||
END IF
|
|
||||||
```
|
|
||||||
|
|
||||||
### Emails Going to Spam
|
### Emails Going to Spam
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,405 +1,379 @@
|
||||||
# Extending BotServer
|
# gbapp: Virtual Crates Architecture
|
||||||
|
|
||||||
This chapter covers how to extend and customize BotServer to meet specific requirements, from creating custom keywords to building new channel adapters and integrating with external systems.
|
This chapter explains how BotServer uses the gbapp concept as virtual crates within the `src/` directory, elegantly mapping the old package system to the new Rust architecture.
|
||||||
|
|
||||||
## Overview
|
## The gbapp Evolution: From Packages to Virtual Crates
|
||||||
|
|
||||||
BotServer is designed to be extensible at multiple levels:
|
### Historical Context (Node.js Era)
|
||||||
- **BASIC Keywords**: Add new commands to the scripting language
|
In previous versions, `.gbapp` packages were external Node.js modules that extended BotServer functionality through a plugin system.
|
||||||
- **Channel Adapters**: Support new messaging platforms
|
|
||||||
- **Storage Backends**: Integrate different storage systems
|
|
||||||
- **Authentication Providers**: Connect to various identity services
|
|
||||||
- **LLM Providers**: Add support for new language models
|
|
||||||
|
|
||||||
## Extension Points
|
### Current Architecture (Rust Era)
|
||||||
|
The `.gbapp` concept now lives as **virtual crates** inside `src/`:
|
||||||
|
- **Virtual Crates**: Each gbapp is a module inside `src/` (like `src/core`, `src/basic`, `src/channels`)
|
||||||
|
- **Same Mental Model**: Developers familiar with the old system can think of each directory as a "package"
|
||||||
|
- **Native Performance**: All code compiles into a single optimized binary
|
||||||
|
- **Contribution Path**: Add new gbapps by creating modules in `src/`
|
||||||
|
|
||||||
### 1. Custom BASIC Keywords
|
## How gbapp Virtual Crates Work
|
||||||
|
|
||||||
Create new keywords by implementing them in Rust:
|
```
|
||||||
|
src/
|
||||||
|
├── core/ # core.gbapp (virtual crate)
|
||||||
|
├── basic/ # basic.gbapp (BASIC interpreter)
|
||||||
|
├── channels/ # channels.gbapp (communication)
|
||||||
|
├── storage/ # storage.gbapp (persistence)
|
||||||
|
├── auth/ # auth.gbapp (authentication)
|
||||||
|
├── llm/ # llm.gbapp (AI integration)
|
||||||
|
└── your_feature/ # your_feature.gbapp (your contribution!)
|
||||||
|
```
|
||||||
|
|
||||||
|
Each directory is conceptually a gbapp - a self-contained module that contributes functionality to the whole.
|
||||||
|
|
||||||
|
## Why This Change?
|
||||||
|
|
||||||
|
1. **Simplicity**: One cohesive codebase instead of fragmented extensions
|
||||||
|
2. **Performance**: Native Rust performance without extension overhead
|
||||||
|
3. **Reliability**: Thoroughly tested core features vs. variable-quality plugins
|
||||||
|
4. **BASIC Power**: BASIC + LLM combination eliminates need for custom code
|
||||||
|
5. **Maintenance**: Easier to maintain one strong core than many extensions
|
||||||
|
|
||||||
|
## Contributing New Keywords
|
||||||
|
|
||||||
|
### Contributing a New gbapp Virtual Crate
|
||||||
|
|
||||||
|
To add functionality, create a new gbapp as a module in `src/`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// src/basic/keywords/my_keyword.rs
|
// src/your_feature/mod.rs - Your gbapp virtual crate
|
||||||
use rhai::{Engine, Dynamic};
|
pub mod keywords;
|
||||||
|
pub mod services;
|
||||||
|
pub mod models;
|
||||||
|
|
||||||
|
// src/your_feature/keywords/mod.rs
|
||||||
use crate::shared::state::AppState;
|
use crate::shared::state::AppState;
|
||||||
|
use rhai::Engine;
|
||||||
|
|
||||||
pub fn register_my_keyword(engine: &mut Engine, state: Arc<AppState>) {
|
pub fn register_keywords(engine: &mut Engine, state: Arc<AppState>) {
|
||||||
engine.register_fn("MY_KEYWORD", move |param: String| -> String {
|
engine.register_fn("YOUR KEYWORD", move |param: String| -> String {
|
||||||
// Your implementation here
|
// Implementation
|
||||||
format!("Processed: {}", param)
|
format!("Result: {}", param)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Register in the keyword module:
|
This maintains the conceptual model of packages while leveraging Rust's module system.
|
||||||
|
|
||||||
|
### Contribution Process for gbapp Virtual Crates
|
||||||
|
|
||||||
|
1. **Fork** the BotServer repository
|
||||||
|
2. **Create** your gbapp module in `src/your_feature/`
|
||||||
|
3. **Structure** it like existing gbapps (core, basic, etc.)
|
||||||
|
4. **Test** thoroughly with unit and integration tests
|
||||||
|
5. **Document** in the appropriate chapter
|
||||||
|
6. **Submit PR** describing your gbapp's purpose
|
||||||
|
|
||||||
|
Example structure for a new gbapp:
|
||||||
|
```
|
||||||
|
src/analytics/ # analytics.gbapp
|
||||||
|
├── mod.rs # Module definition
|
||||||
|
├── keywords.rs # BASIC keywords
|
||||||
|
├── services.rs # Core services
|
||||||
|
├── models.rs # Data models
|
||||||
|
└── tests.rs # Unit tests
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding New Components
|
||||||
|
|
||||||
|
Components are features compiled into BotServer via Cargo features:
|
||||||
|
|
||||||
|
### Current Components in Cargo.toml
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
# Core features
|
||||||
|
chat = [] # Chat functionality
|
||||||
|
drive = [] # Storage system
|
||||||
|
tasks = [] # Task management
|
||||||
|
calendar = [] # Calendar integration
|
||||||
|
meet = [] # Video meetings
|
||||||
|
mail = [] # Email system
|
||||||
|
|
||||||
|
# Enterprise features
|
||||||
|
compliance = [] # Compliance tools
|
||||||
|
attendance = [] # Attendance tracking
|
||||||
|
directory = [] # User directory
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding a New Component
|
||||||
|
|
||||||
|
1. **Define Feature** in `Cargo.toml`:
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
your_feature = ["dep:required_crate"]
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Implement** in appropriate module:
|
||||||
```rust
|
```rust
|
||||||
// src/basic/keywords/mod.rs
|
#[cfg(feature = "your_feature")]
|
||||||
pub fn register_all_keywords(engine: &mut Engine, state: Arc<AppState>) {
|
pub mod your_feature {
|
||||||
// ... existing keywords
|
// Implementation
|
||||||
register_my_keyword(engine, state.clone());
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Use in BASIC scripts:
|
3. **Register** in `installer.rs`:
|
||||||
```basic
|
```rust
|
||||||
result = MY_KEYWORD "input data"
|
fn register_your_feature(&mut self) {
|
||||||
TALK result
|
self.components.insert(
|
||||||
|
"your_feature",
|
||||||
|
Component {
|
||||||
|
name: "Your Feature",
|
||||||
|
description: "Feature description",
|
||||||
|
port: None,
|
||||||
|
setup_required: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Channel Adapters
|
## Understanding the gbapp → Virtual Crate Mapping
|
||||||
|
|
||||||
Implement a new messaging channel:
|
The transition from Node.js packages to Rust modules maintains conceptual familiarity:
|
||||||
|
|
||||||
|
| Old (Node.js) | New (Rust) | Location | Purpose |
|
||||||
|
|---------------|------------|----------|---------|
|
||||||
|
| `core.gbapp` | `core` module | `src/core/` | Core engine functionality |
|
||||||
|
| `basic.gbapp` | `basic` module | `src/basic/` | BASIC interpreter |
|
||||||
|
| `whatsapp.gbapp` | `channels::whatsapp` | `src/channels/whatsapp/` | WhatsApp integration |
|
||||||
|
| `kb.gbapp` | `storage::kb` | `src/storage/kb/` | Knowledge base |
|
||||||
|
| `custom.gbapp` | `custom` module | `src/custom/` | Your contribution |
|
||||||
|
|
||||||
|
### Creating Private gbapp Virtual Crates
|
||||||
|
|
||||||
|
For proprietary features, you can still create private gbapps:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// src/channels/my_channel.rs
|
// Fork BotServer, then add your private gbapp
|
||||||
use async_trait::async_trait;
|
// src/proprietary/mod.rs
|
||||||
use crate::channels::traits::ChannelAdapter;
|
#[cfg(feature = "proprietary")]
|
||||||
|
pub mod my_private_feature {
|
||||||
pub struct MyChannelAdapter {
|
// Your private implementation
|
||||||
config: MyChannelConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl ChannelAdapter for MyChannelAdapter {
|
|
||||||
async fn send_message(&self, recipient: &str, message: &str) -> Result<()> {
|
|
||||||
// Send message implementation
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn receive_message(&self) -> Result<Message> {
|
|
||||||
// Receive message implementation
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn send_attachment(&self, recipient: &str, file: &[u8]) -> Result<()> {
|
|
||||||
// Send file implementation
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Storage Providers
|
Then in `Cargo.toml`:
|
||||||
|
```toml
|
||||||
Add support for new storage backends:
|
[features]
|
||||||
|
proprietary = []
|
||||||
```rust
|
|
||||||
// src/storage/my_storage.rs
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use crate::storage::traits::StorageProvider;
|
|
||||||
|
|
||||||
pub struct MyStorageProvider {
|
|
||||||
client: MyStorageClient,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl StorageProvider for MyStorageProvider {
|
|
||||||
async fn get(&self, key: &str) -> Result<Vec<u8>> {
|
|
||||||
// Retrieve object
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn put(&self, key: &str, data: &[u8]) -> Result<()> {
|
|
||||||
// Store object
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn delete(&self, key: &str) -> Result<()> {
|
|
||||||
// Delete object
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn list(&self, prefix: &str) -> Result<Vec<String>> {
|
|
||||||
// List objects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture for Extensions
|
This keeps your code separate while benefiting from core updates.
|
||||||
|
|
||||||
### Plugin System
|
### Benefits of the Virtual Crate Approach
|
||||||
|
|
||||||
BotServer uses a modular architecture that supports plugins:
|
1. **Familiar Mental Model**: Developers understand "packages"
|
||||||
|
2. **Clean Separation**: Each gbapp is self-contained
|
||||||
|
3. **Easy Discovery**: All gbapps visible in `src/`
|
||||||
|
4. **Native Performance**: Everything compiles together
|
||||||
|
5. **Type Safety**: Rust ensures interfaces are correct
|
||||||
|
|
||||||
|
## Real Examples of gbapp Virtual Crates in src/
|
||||||
|
|
||||||
```
|
```
|
||||||
botserver/
|
src/
|
||||||
├── src/
|
├── core/ # Core gbapp - Bootstrap, package manager
|
||||||
│ ├── core/ # Core functionality
|
│ ├── mod.rs
|
||||||
│ ├── basic/ # BASIC interpreter
|
│ ├── bootstrap.rs
|
||||||
│ │ └── keywords/ # Keyword implementations
|
│ └── package_manager/
|
||||||
│ ├── channels/ # Channel adapters
|
│
|
||||||
│ ├── storage/ # Storage providers
|
├── basic/ # BASIC gbapp - Interpreter and keywords
|
||||||
│ ├── auth/ # Authentication modules
|
│ ├── mod.rs
|
||||||
│ └── llm/ # LLM integrations
|
│ ├── interpreter.rs
|
||||||
|
│ └── keywords/
|
||||||
|
│ ├── mod.rs
|
||||||
|
│ ├── talk.rs
|
||||||
|
│ ├── hear.rs
|
||||||
|
│ └── llm.rs
|
||||||
|
│
|
||||||
|
├── channels/ # Channels gbapp - Communication adapters
|
||||||
|
│ ├── mod.rs
|
||||||
|
│ ├── whatsapp.rs
|
||||||
|
│ ├── teams.rs
|
||||||
|
│ └── email.rs
|
||||||
|
│
|
||||||
|
└── analytics/ # Your new gbapp!
|
||||||
|
├── mod.rs
|
||||||
|
├── keywords.rs # ADD ANALYTICS, GET METRICS
|
||||||
|
└── services.rs # Analytics engine
|
||||||
```
|
```
|
||||||
|
|
||||||
### Dependency Injection
|
## Development Environment
|
||||||
|
|
||||||
Extensions use dependency injection for configuration:
|
### System Requirements
|
||||||
|
|
||||||
```rust
|
- **Disk Space**: 8GB minimum for development
|
||||||
// Configuration
|
- **RAM**: 8GB recommended
|
||||||
#[derive(Deserialize)]
|
- **Database**: Any SQL database (abstracted)
|
||||||
pub struct ExtensionConfig {
|
- **Storage**: Any S3-compatible storage (abstracted)
|
||||||
pub enabled: bool,
|
|
||||||
pub options: HashMap<String, String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Registration
|
### No Brand Lock-in
|
||||||
pub fn register_extension(app_state: &mut AppState, config: ExtensionConfig) {
|
|
||||||
if config.enabled {
|
BotServer uses generic terms:
|
||||||
let extension = MyExtension::new(config.options);
|
- ❌ PostgreSQL → ✅ "database"
|
||||||
app_state.extensions.push(Box::new(extension));
|
- ❌ MinIO → ✅ "drive storage"
|
||||||
}
|
- ❌ Qdrant → ✅ "vector database"
|
||||||
}
|
- ❌ Redis → ✅ "cache"
|
||||||
|
|
||||||
|
This ensures vendor neutrality and flexibility.
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
### Regular Audits
|
||||||
|
|
||||||
|
Run security audits regularly:
|
||||||
|
```bash
|
||||||
|
cargo audit
|
||||||
```
|
```
|
||||||
|
|
||||||
## Common Extension Patterns
|
This checks for known vulnerabilities in dependencies.
|
||||||
|
|
||||||
### 1. API Integration
|
### Secure Coding
|
||||||
|
|
||||||
Create a keyword for external API calls:
|
When contributing:
|
||||||
|
- Validate all inputs
|
||||||
|
- Use safe Rust patterns
|
||||||
|
- Avoid `unsafe` blocks
|
||||||
|
- Handle errors properly
|
||||||
|
- Add security tests
|
||||||
|
|
||||||
```rust
|
## Testing Your Contributions
|
||||||
pub fn register_api_keyword(engine: &mut Engine) {
|
|
||||||
engine.register_fn("CALL_API", |url: String, method: String| -> Dynamic {
|
|
||||||
let runtime = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
runtime.block_on(async {
|
|
||||||
let client = reqwest::Client::new();
|
|
||||||
let response = match method.as_str() {
|
|
||||||
"GET" => client.get(&url).send().await,
|
|
||||||
"POST" => client.post(&url).send().await,
|
|
||||||
_ => return Dynamic::from("Invalid method"),
|
|
||||||
};
|
|
||||||
|
|
||||||
match response {
|
|
||||||
Ok(resp) => Dynamic::from(resp.text().await.unwrap_or_default()),
|
|
||||||
Err(_) => Dynamic::from("Error calling API"),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Database Operations
|
|
||||||
|
|
||||||
Add custom database queries:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub fn register_db_keyword(engine: &mut Engine, state: Arc<AppState>) {
|
|
||||||
let state_clone = state.clone();
|
|
||||||
engine.register_fn("QUERY_DB", move |sql: String| -> Vec<Dynamic> {
|
|
||||||
let mut conn = state_clone.conn.get().unwrap();
|
|
||||||
|
|
||||||
// Execute query (with proper sanitization)
|
|
||||||
let results = diesel::sql_query(sql)
|
|
||||||
.load::<CustomResult>(&mut conn)
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
// Convert to Dynamic
|
|
||||||
results.into_iter()
|
|
||||||
.map(|r| Dynamic::from(r))
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Event Handlers
|
|
||||||
|
|
||||||
Implement custom event processing:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub trait EventHandler: Send + Sync {
|
|
||||||
fn handle_event(&self, event: Event) -> Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CustomEventHandler;
|
|
||||||
|
|
||||||
impl EventHandler for CustomEventHandler {
|
|
||||||
fn handle_event(&self, event: Event) -> Result<()> {
|
|
||||||
match event {
|
|
||||||
Event::MessageReceived(msg) => {
|
|
||||||
// Process incoming message
|
|
||||||
},
|
|
||||||
Event::SessionStarted(session) => {
|
|
||||||
// Initialize session
|
|
||||||
},
|
|
||||||
Event::Error(err) => {
|
|
||||||
// Handle errors
|
|
||||||
},
|
|
||||||
_ => Ok(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing Extensions
|
|
||||||
|
|
||||||
### Unit Tests
|
### Unit Tests
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_my_keyword() {
|
fn test_keyword() {
|
||||||
let mut engine = Engine::new();
|
// Test your keyword
|
||||||
register_my_keyword(&mut engine);
|
|
||||||
|
|
||||||
let result: String = engine.eval(r#"MY_KEYWORD "test""#).unwrap();
|
|
||||||
assert_eq!(result, "Processed: test");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Integration Tests
|
### Integration Tests
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_channel_adapter() {
|
async fn test_feature() {
|
||||||
let adapter = MyChannelAdapter::new(test_config());
|
// Test feature integration
|
||||||
|
|
||||||
// Test sending
|
|
||||||
let result = adapter.send_message("user123", "Test message").await;
|
|
||||||
assert!(result.is_ok());
|
|
||||||
|
|
||||||
// Test receiving
|
|
||||||
let message = adapter.receive_message().await.unwrap();
|
|
||||||
assert_eq!(message.content, "Expected response");
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Deployment Considerations
|
### BASIC Script Tests
|
||||||
|
```basic
|
||||||
### Configuration
|
' test_script.bas
|
||||||
|
result = YOUR KEYWORD "test"
|
||||||
Extensions are configured in `config.csv`:
|
IF result != "expected" THEN
|
||||||
|
TALK "Test failed"
|
||||||
```csv
|
ELSE
|
||||||
name,value
|
TALK "Test passed"
|
||||||
extension_my_feature,enabled
|
END IF
|
||||||
extension_my_feature_option1,value1
|
|
||||||
extension_my_feature_option2,value2
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Performance Impact
|
## Documentation Requirements
|
||||||
|
|
||||||
Consider performance when adding extensions:
|
All contributions must include:
|
||||||
- Use async operations for I/O
|
|
||||||
- Implement caching where appropriate
|
|
||||||
- Profile resource usage
|
|
||||||
- Add metrics and monitoring
|
|
||||||
|
|
||||||
### Security
|
1. **Keyword Documentation** in Chapter 6
|
||||||
|
2. **Architecture Updates** if structural changes
|
||||||
|
3. **API Documentation** for new endpoints
|
||||||
|
4. **BASIC Examples** showing usage
|
||||||
|
5. **Migration Guide** if breaking changes
|
||||||
|
|
||||||
Ensure extensions are secure:
|
## Performance Considerations
|
||||||
- Validate all input
|
|
||||||
- Use prepared statements for database queries
|
|
||||||
- Implement rate limiting
|
|
||||||
- Add authentication where needed
|
|
||||||
- Follow least privilege principle
|
|
||||||
|
|
||||||
## Best Practices
|
### Benchmarking
|
||||||
|
|
||||||
### 1. Error Handling
|
Before submitting:
|
||||||
|
```bash
|
||||||
Always handle errors gracefully:
|
cargo bench
|
||||||
|
|
||||||
```rust
|
|
||||||
pub fn my_extension_function() -> Result<String> {
|
|
||||||
// Use ? operator for error propagation
|
|
||||||
let data = fetch_data()?;
|
|
||||||
let processed = process_data(data)?;
|
|
||||||
Ok(format!("Success: {}", processed))
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Logging
|
### Profiling
|
||||||
|
|
||||||
Add comprehensive logging:
|
Identify bottlenecks:
|
||||||
|
```bash
|
||||||
```rust
|
cargo flamegraph
|
||||||
use log::{info, warn, error, debug};
|
|
||||||
|
|
||||||
pub fn process_request(req: Request) {
|
|
||||||
debug!("Processing request: {:?}", req);
|
|
||||||
|
|
||||||
match handle_request(req) {
|
|
||||||
Ok(result) => info!("Request successful: {}", result),
|
|
||||||
Err(e) => error!("Request failed: {}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Documentation
|
## Community Guidelines
|
||||||
|
|
||||||
Document your extensions:
|
### What We Accept
|
||||||
|
|
||||||
```rust
|
✅ New BASIC keywords that benefit many users
|
||||||
/// Custom keyword for data processing
|
✅ Performance improvements
|
||||||
///
|
✅ Bug fixes with tests
|
||||||
/// # Arguments
|
✅ Documentation improvements
|
||||||
/// * `input` - The data to process
|
✅ Security enhancements
|
||||||
///
|
|
||||||
/// # Returns
|
### What We Don't Accept
|
||||||
/// Processed data as a string
|
|
||||||
///
|
❌ Vendor-specific integrations (use generic interfaces)
|
||||||
/// # Example
|
❌ Extensions that bypass BASIC
|
||||||
/// ```basic
|
❌ Features achievable with existing keywords
|
||||||
/// result = PROCESS_DATA "raw input"
|
❌ Undocumented code
|
||||||
/// ```
|
❌ Code without tests
|
||||||
pub fn process_data_keyword(input: String) -> String {
|
|
||||||
// Implementation
|
## The Power of BASIC + LLM
|
||||||
}
|
|
||||||
|
Remember: In 2025, 100% BASIC/LLM applications are reality. Before adding a keyword, consider:
|
||||||
|
|
||||||
|
1. Can this be done with existing keywords + LLM?
|
||||||
|
2. Will this keyword benefit multiple use cases?
|
||||||
|
3. Does it follow the BASIC philosophy of simplicity?
|
||||||
|
|
||||||
|
### Example: No Custom Code Needed
|
||||||
|
|
||||||
|
Instead of custom integration code:
|
||||||
|
```basic
|
||||||
|
' Everything in BASIC
|
||||||
|
data = GET "api.example.com/data"
|
||||||
|
processed = LLM "Process this data: " + data
|
||||||
|
result = FIND "table", "criteria=" + processed
|
||||||
|
SEND MAIL user, "Results", result
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples of Extensions
|
## Future Direction
|
||||||
|
|
||||||
### Weather Integration
|
BotServer's future is:
|
||||||
|
- **Stronger Core**: More powerful built-in keywords
|
||||||
|
- **Better LLM Integration**: Smarter AI capabilities
|
||||||
|
- **Simpler BASIC**: Even easier scripting
|
||||||
|
- **Community-Driven**: Features requested by users
|
||||||
|
|
||||||
```rust
|
## How to Get Started
|
||||||
pub fn register_weather_keyword(engine: &mut Engine) {
|
|
||||||
engine.register_fn("GET_WEATHER", |city: String| -> String {
|
|
||||||
// Call weather API
|
|
||||||
let api_key = std::env::var("WEATHER_API_KEY").unwrap_or_default();
|
|
||||||
let url = format!("https://api.weather.com/v1/weather?city={}&key={}", city, api_key);
|
|
||||||
|
|
||||||
// Fetch and parse response
|
|
||||||
// Return weather information
|
|
||||||
});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Custom Analytics
|
1. **Fork** the repository
|
||||||
|
2. **Read** existing code in `src/basic/keywords/`
|
||||||
```rust
|
3. **Discuss** your idea in GitHub Issues
|
||||||
pub struct AnalyticsExtension {
|
4. **Implement** following the patterns
|
||||||
client: AnalyticsClient,
|
5. **Test** thoroughly
|
||||||
}
|
6. **Document** completely
|
||||||
|
7. **Submit** PR with clear explanation
|
||||||
impl AnalyticsExtension {
|
|
||||||
pub fn track_event(&self, event: &str, properties: HashMap<String, String>) {
|
|
||||||
self.client.track(Event {
|
|
||||||
name: event.to_string(),
|
|
||||||
properties,
|
|
||||||
timestamp: Utc::now(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
Extending BotServer allows you to:
|
The `.gbapp` concept has elegantly evolved from external Node.js packages to **virtual crates** within `src/`. This approach:
|
||||||
- Add domain-specific functionality
|
- **Preserves the mental model** developers are familiar with
|
||||||
- Integrate with existing systems
|
- **Maps perfectly** to Rust's module system
|
||||||
- Support new communication channels
|
- **Encourages contribution** by making the structure clear
|
||||||
- Implement custom business logic
|
- **Maintains separation** while compiling to a single binary
|
||||||
- Enhance the platform's capabilities
|
|
||||||
|
|
||||||
The modular architecture and clear extension points make it straightforward to add new features while maintaining system stability and performance.
|
Each directory in `src/` is effectively a gbapp - contribute by adding your own! With BASIC + LLM handling the complexity, your gbapp just needs to provide the right keywords and services.
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [Prompt Manager](./prompt-manager.md) - Managing AI prompts and responses
|
- [Philosophy](./philosophy.md) - The gbapp philosophy: Let machines do machine work
|
||||||
- [Hooks System](./hooks.md) - Event-driven extensions
|
- [Architecture](./architecture.md) - System architecture
|
||||||
- [Adapter Development](./adapters.md) - Creating custom adapters
|
- [Building](./building.md) - Build process
|
||||||
- [Chapter 2: Packages](../chapter-02/README.md) - Understanding bot components
|
- [Custom Keywords](./custom-keywords.md) - Keyword implementation
|
||||||
- [Chapter 3: KB and Tools](../chapter-03/kb-and-tools.md) - Knowledge base and tool system
|
- [Services](./services.md) - Core services
|
||||||
- [Chapter 5: BASIC Reference](../chapter-05/README.md) - Complete command reference
|
- [Chapter 6: BASIC Reference](../chapter-06-gbdialog/README.md) - BASIC language
|
||||||
- [Chapter 8: External APIs](../chapter-08/external-apis.md) - API integration patterns
|
- [Chapter 9: API](../chapter-09-api/README.md) - API documentation
|
||||||
- [Chapter 9: Advanced Topics](../chapter-09/README.md) - Advanced features
|
|
||||||
- [Chapter 10: Development](../chapter-10/README.md) - Development tools and practices
|
|
||||||
|
|
|
||||||
|
|
@ -4,50 +4,15 @@ BotServer follows a modular architecture designed for scalability, maintainabili
|
||||||
|
|
||||||
## Core Architecture
|
## Core Architecture
|
||||||
|
|
||||||
### System Architecture Diagram
|
### Data Flow Architecture
|
||||||
|
|
||||||
```
|

|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ BotServer (Binary) │
|
|
||||||
├─────────────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ ┌────────────────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ Core Engine │ │
|
|
||||||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
|
||||||
│ │ │ BASIC │ │ Session │ │ Context │ │ │
|
|
||||||
│ │ │ Interpreter │ │ Manager │ │ Manager │ │ │
|
|
||||||
│ │ │ (Rhai) │ │ (Tokio) │ │ (Memory) │ │ │
|
|
||||||
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
|
|
||||||
│ └─────────┼──────────────────┼──────────────────┼───────────────────┘ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ ┌─────────▼──────────────────▼──────────────────▼───────────────────┐ │
|
|
||||||
│ │ AI & NLP Layer │ │
|
|
||||||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
|
||||||
│ │ │ LLM │ │ Embeddings │ │ Knowledge │ │ │
|
|
||||||
│ │ │ Integration │ │ (BGE) │ │ Base │ │ │
|
|
||||||
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
|
|
||||||
│ └─────────┼──────────────────┼──────────────────┼───────────────────┘ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ ┌─────────▼──────────────────▼──────────────────▼───────────────────┐ │
|
|
||||||
│ │ Communication Layer │ │
|
|
||||||
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
|
|
||||||
│ │ │ WebSocket │ │ REST API │ │ Channels │ │ │
|
|
||||||
│ │ │ Server │ │ (Axum) │ │ Adapters │ │ │
|
|
||||||
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
|
|
||||||
│ └─────────┼──────────────────┼──────────────────┼───────────────────┘ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ ┌─────────▼──────────────────▼──────────────────▼───────────────────┐ │
|
|
||||||
│ │ Storage Layer │ │
|
|
||||||
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
|
|
||||||
│ │ │PostgreSQL│ │ Valkey │ │ SeaweedFS│ │ Qdrant │ │ │
|
|
||||||
│ │ │ (Diesel) │ │ Cache │ │ S3 │ │ Vectors │ │ │
|
|
||||||
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
|
|
||||||
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### Module Dependency Graph
|
### System Architecture
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Module Dependency Graph
|
||||||
|
|
||||||
```
|
```
|
||||||
main.rs
|
main.rs
|
||||||
|
|
|
||||||
139
docs/src/chapter-07-gbapp/assets/data-flow.svg
Normal file
139
docs/src/chapter-07-gbapp/assets/data-flow.svg
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||||
|
<path d="M0,0 L0,6 L9,3 z" fill="#666" opacity="0.8"/>
|
||||||
|
</marker>
|
||||||
|
<linearGradient id="gradient1" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#4A90E2;stop-opacity:0.1" />
|
||||||
|
<stop offset="100%" style="stop-color:#4A90E2;stop-opacity:0.3" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="gradient2" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#50C878;stop-opacity:0.1" />
|
||||||
|
<stop offset="100%" style="stop-color:#50C878;stop-opacity:0.3" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="gradient3" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#FF6B6B;stop-opacity:0.1" />
|
||||||
|
<stop offset="100%" style="stop-color:#FF6B6B;stop-opacity:0.3" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<text x="400" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#333">BotServer Data Flow Architecture</text>
|
||||||
|
|
||||||
|
<!-- User Input Layer -->
|
||||||
|
<g id="user-layer">
|
||||||
|
<rect x="50" y="60" width="700" height="80" fill="url(#gradient1)" stroke="#4A90E2" stroke-width="2" rx="8" opacity="0.8"/>
|
||||||
|
<text x="400" y="85" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#333">User Input Layer</text>
|
||||||
|
|
||||||
|
<!-- Input sources -->
|
||||||
|
<rect x="80" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="140" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">Web UI</text>
|
||||||
|
|
||||||
|
<rect x="220" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="280" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">WhatsApp</text>
|
||||||
|
|
||||||
|
<rect x="360" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="420" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">Teams</text>
|
||||||
|
|
||||||
|
<rect x="500" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="560" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">Email</text>
|
||||||
|
|
||||||
|
<rect x="640" y="95" width="80" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="680" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">API</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Arrows from User Layer to Processing -->
|
||||||
|
<line x1="400" y1="140" x2="400" y2="170" stroke="#666" stroke-width="2" marker-end="url(#arrow)" opacity="0.6"/>
|
||||||
|
|
||||||
|
<!-- Processing Layer -->
|
||||||
|
<g id="processing-layer">
|
||||||
|
<rect x="50" y="170" width="700" height="200" fill="url(#gradient2)" stroke="#50C878" stroke-width="2" rx="8" opacity="0.8"/>
|
||||||
|
<text x="400" y="195" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#333">Core Processing Engine</text>
|
||||||
|
|
||||||
|
<!-- Session Manager -->
|
||||||
|
<rect x="80" y="210" width="150" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="155" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Session Manager</text>
|
||||||
|
<text x="155" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">User Context</text>
|
||||||
|
|
||||||
|
<!-- BASIC Interpreter -->
|
||||||
|
<rect x="250" y="210" width="150" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="325" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">BASIC Interpreter</text>
|
||||||
|
<text x="325" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Script Execution</text>
|
||||||
|
|
||||||
|
<!-- LLM Integration -->
|
||||||
|
<rect x="420" y="210" width="150" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="495" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">LLM Integration</text>
|
||||||
|
<text x="495" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">AI Processing</text>
|
||||||
|
|
||||||
|
<!-- Knowledge Base -->
|
||||||
|
<rect x="590" y="210" width="130" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="655" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Knowledge Base</text>
|
||||||
|
<text x="655" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Vector Search</text>
|
||||||
|
|
||||||
|
<!-- Internal flow arrows -->
|
||||||
|
<line x1="230" y1="240" x2="250" y2="240" stroke="#666" stroke-width="1" marker-end="url(#arrow)" opacity="0.5"/>
|
||||||
|
<line x1="400" y1="240" x2="420" y2="240" stroke="#666" stroke-width="1" marker-end="url(#arrow)" opacity="0.5"/>
|
||||||
|
<line x1="570" y1="240" x2="590" y2="240" stroke="#666" stroke-width="1" marker-end="url(#arrow)" opacity="0.5"/>
|
||||||
|
|
||||||
|
<!-- Tool System -->
|
||||||
|
<rect x="80" y="290" width="300" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="230" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Tool System</text>
|
||||||
|
<text x="230" y="332" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">External APIs & Functions</text>
|
||||||
|
|
||||||
|
<!-- Cache Layer -->
|
||||||
|
<rect x="420" y="290" width="300" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="570" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Cache Layer</text>
|
||||||
|
<text x="570" y="332" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Response Optimization</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Arrows from Processing to Storage -->
|
||||||
|
<line x1="400" y1="370" x2="400" y2="400" stroke="#666" stroke-width="2" marker-end="url(#arrow)" opacity="0.6"/>
|
||||||
|
|
||||||
|
<!-- Storage Layer -->
|
||||||
|
<g id="storage-layer">
|
||||||
|
<rect x="50" y="400" width="700" height="120" fill="url(#gradient3)" stroke="#FF6B6B" stroke-width="2" rx="8" opacity="0.8"/>
|
||||||
|
<text x="400" y="425" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#333">Storage & Persistence Layer</text>
|
||||||
|
|
||||||
|
<!-- Database -->
|
||||||
|
<rect x="80" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="150" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Database</text>
|
||||||
|
<text x="150" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">User Data</text>
|
||||||
|
|
||||||
|
<!-- Vector DB -->
|
||||||
|
<rect x="240" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="310" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Vector DB</text>
|
||||||
|
<text x="310" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Embeddings</text>
|
||||||
|
|
||||||
|
<!-- Drive Storage -->
|
||||||
|
<rect x="400" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="470" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Drive Storage</text>
|
||||||
|
<text x="470" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Files & Assets</text>
|
||||||
|
|
||||||
|
<!-- Cache -->
|
||||||
|
<rect x="560" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
|
||||||
|
<text x="630" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Cache</text>
|
||||||
|
<text x="630" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Fast Access</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Bidirectional arrows showing data flow -->
|
||||||
|
<g id="flow-arrows" opacity="0.4">
|
||||||
|
<!-- Vertical flows -->
|
||||||
|
<line x1="155" y1="270" x2="155" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
|
||||||
|
<line x1="325" y1="270" x2="310" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
|
||||||
|
<line x1="495" y1="270" x2="470" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
|
||||||
|
<line x1="655" y1="270" x2="630" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Legend -->
|
||||||
|
<g id="legend" transform="translate(50, 540)">
|
||||||
|
<text x="0" y="0" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Data Flow:</text>
|
||||||
|
<line x1="80" y1="-5" x2="120" y2="-5" stroke="#666" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<text x="125" y="0" font-family="Arial, sans-serif" font-size="11" fill="#666">Request/Response</text>
|
||||||
|
|
||||||
|
<line x1="250" y1="-5" x2="290" y2="-5" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
|
||||||
|
<text x="295" y="0" font-family="Arial, sans-serif" font-size="11" fill="#666">Data Access</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Performance Note -->
|
||||||
|
<text x="400" y="580" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#999">All components run in async Rust for maximum performance</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 9.5 KiB |
155
docs/src/chapter-07-gbapp/assets/system-architecture.svg
Normal file
155
docs/src/chapter-07-gbapp/assets/system-architecture.svg
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
<svg width="900" height="700" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 700">
|
||||||
|
<defs>
|
||||||
|
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
|
||||||
|
<path d="M0,0 L0,6 L9,3 z" fill="#666"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<text x="450" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="22" font-weight="bold" fill="#1F2937">BotServer Architecture - Virtual Crates System</text>
|
||||||
|
|
||||||
|
<!-- Main Container -->
|
||||||
|
<rect x="40" y="50" width="820" height="620" fill="none" stroke="#E5E7EB" stroke-width="2" rx="12" stroke-opacity="0.5"/>
|
||||||
|
|
||||||
|
<!-- Binary Output -->
|
||||||
|
<rect x="350" y="70" width="200" height="40" fill="#EBF8FF" stroke="#2563EB" stroke-width="2" rx="8"/>
|
||||||
|
<text x="450" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#1F2937">BotServer Binary</text>
|
||||||
|
|
||||||
|
<!-- Compilation Arrow -->
|
||||||
|
<line x1="450" y1="110" x2="450" y2="140" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" stroke-dasharray="5,3" opacity="0.6"/>
|
||||||
|
<text x="470" y="130" font-family="Arial, sans-serif" font-size="10" fill="#6B7280">compiles to</text>
|
||||||
|
|
||||||
|
<!-- Core Layer -->
|
||||||
|
<g id="core-layer">
|
||||||
|
<rect x="60" y="140" width="780" height="120" fill="#EBF8FF" fill-opacity="0.3" stroke="#2563EB" stroke-width="2" rx="8"/>
|
||||||
|
<text x="450" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#1F2937">Core Engine (src/core/)</text>
|
||||||
|
|
||||||
|
<!-- Core Components -->
|
||||||
|
<rect x="80" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
|
||||||
|
<text x="150" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Bootstrap</text>
|
||||||
|
<text x="150" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">System Init</text>
|
||||||
|
<text x="150" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Service Start</text>
|
||||||
|
|
||||||
|
<rect x="240" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
|
||||||
|
<text x="310" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Package Manager</text>
|
||||||
|
<text x="310" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Component Registry</text>
|
||||||
|
<text x="310" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Module Loader</text>
|
||||||
|
|
||||||
|
<rect x="400" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
|
||||||
|
<text x="470" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Session Manager</text>
|
||||||
|
<text x="470" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Context Handling</text>
|
||||||
|
<text x="470" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">State Management</text>
|
||||||
|
|
||||||
|
<rect x="560" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
|
||||||
|
<text x="630" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Shared State</text>
|
||||||
|
<text x="630" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">AppState</text>
|
||||||
|
<text x="630" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Configuration</text>
|
||||||
|
|
||||||
|
<rect x="720" y="185" width="100" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
|
||||||
|
<text x="770" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Utils</text>
|
||||||
|
<text x="770" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Helpers</text>
|
||||||
|
<text x="770" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Common</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Bidirectional Arrow -->
|
||||||
|
<line x1="450" y1="260" x2="450" y2="290" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" opacity="0.6"/>
|
||||||
|
<line x1="460" y1="290" x2="460" y2="260" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" opacity="0.6"/>
|
||||||
|
|
||||||
|
<!-- Virtual Crates Layer (gbapps) -->
|
||||||
|
<g id="gbapp-layer">
|
||||||
|
<rect x="60" y="290" width="780" height="180" fill="#D1FAE5" fill-opacity="0.3" stroke="#10B981" stroke-width="2" rx="8"/>
|
||||||
|
<text x="450" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#1F2937">Virtual Crates (gbapp modules in src/)</text>
|
||||||
|
|
||||||
|
<!-- BASIC gbapp -->
|
||||||
|
<rect x="80" y="335" width="170" height="115" fill="white" stroke="#10B981" stroke-width="1" rx="4"/>
|
||||||
|
<text x="165" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">basic.gbapp</text>
|
||||||
|
<text x="165" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/basic/</text>
|
||||||
|
<line x1="90" y1="378" x2="240" y2="378" stroke="#E5E7EB" stroke-width="1"/>
|
||||||
|
<text x="165" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• BASIC Interpreter</text>
|
||||||
|
<text x="165" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Keywords Registry</text>
|
||||||
|
<text x="165" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Script Execution</text>
|
||||||
|
<text x="165" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Rhai Engine</text>
|
||||||
|
|
||||||
|
<!-- Channels gbapp -->
|
||||||
|
<rect x="270" y="335" width="170" height="115" fill="white" stroke="#10B981" stroke-width="1" rx="4"/>
|
||||||
|
<text x="355" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">channels.gbapp</text>
|
||||||
|
<text x="355" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/channels/</text>
|
||||||
|
<line x1="280" y1="378" x2="430" y2="378" stroke="#E5E7EB" stroke-width="1"/>
|
||||||
|
<text x="355" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• WhatsApp</text>
|
||||||
|
<text x="355" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Teams</text>
|
||||||
|
<text x="355" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Email</text>
|
||||||
|
<text x="355" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Web UI</text>
|
||||||
|
|
||||||
|
<!-- Storage gbapp -->
|
||||||
|
<rect x="460" y="335" width="170" height="115" fill="white" stroke="#10B981" stroke-width="1" rx="4"/>
|
||||||
|
<text x="545" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">storage.gbapp</text>
|
||||||
|
<text x="545" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/storage/</text>
|
||||||
|
<line x1="470" y1="378" x2="620" y2="378" stroke="#E5E7EB" stroke-width="1"/>
|
||||||
|
<text x="545" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Knowledge Base</text>
|
||||||
|
<text x="545" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Drive Integration</text>
|
||||||
|
<text x="545" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Vector DB</text>
|
||||||
|
<text x="545" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Cache</text>
|
||||||
|
|
||||||
|
<!-- Custom gbapp (Your Contribution) -->
|
||||||
|
<rect x="650" y="335" width="170" height="115" fill="#FEF3C7" stroke="#F59E0B" stroke-width="2" rx="4" stroke-dasharray="5,3"/>
|
||||||
|
<text x="735" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">your_feature.gbapp</text>
|
||||||
|
<text x="735" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/your_feature/</text>
|
||||||
|
<line x1="660" y1="378" x2="810" y2="378" stroke="#E5E7EB" stroke-width="1"/>
|
||||||
|
<text x="735" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-style="italic" fill="#6B7280">• Your Keywords</text>
|
||||||
|
<text x="735" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-style="italic" fill="#6B7280">• Your Services</text>
|
||||||
|
<text x="735" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-style="italic" fill="#6B7280">• Your Models</text>
|
||||||
|
<text x="735" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-weight="bold" fill="#F59E0B">+ Add yours!</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Arrow from gbapp to AI -->
|
||||||
|
<line x1="450" y1="470" x2="450" y2="500" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" opacity="0.6"/>
|
||||||
|
|
||||||
|
<!-- AI/LLM Layer -->
|
||||||
|
<g id="ai-layer">
|
||||||
|
<rect x="60" y="500" width="380" height="80" fill="#EDE9FE" fill-opacity="0.3" stroke="#8B5CF6" stroke-width="2" rx="8"/>
|
||||||
|
<text x="250" y="525" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#1F2937">AI & LLM Integration</text>
|
||||||
|
|
||||||
|
<rect x="80" y="535" width="100" height="35" fill="white" stroke="#8B5CF6" stroke-width="1" rx="4"/>
|
||||||
|
<text x="130" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">LLM Service</text>
|
||||||
|
|
||||||
|
<rect x="195" y="535" width="100" height="35" fill="white" stroke="#8B5CF6" stroke-width="1" rx="4"/>
|
||||||
|
<text x="245" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Embeddings</text>
|
||||||
|
|
||||||
|
<rect x="310" y="535" width="110" height="35" fill="white" stroke="#8B5CF6" stroke-width="1" rx="4"/>
|
||||||
|
<text x="365" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Semantic Search</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Storage Layer -->
|
||||||
|
<g id="storage-layer">
|
||||||
|
<rect x="460" y="500" width="380" height="80" fill="#FEE2E2" fill-opacity="0.3" stroke="#EF4444" stroke-width="2" rx="8"/>
|
||||||
|
<text x="650" y="525" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#1F2937">Persistence Layer</text>
|
||||||
|
|
||||||
|
<rect x="480" y="535" width="85" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
|
||||||
|
<text x="522" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Database</text>
|
||||||
|
|
||||||
|
<rect x="580" y="535" width="85" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
|
||||||
|
<text x="622" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Vector DB</text>
|
||||||
|
|
||||||
|
<rect x="680" y="535" width="70" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
|
||||||
|
<text x="715" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Drive</text>
|
||||||
|
|
||||||
|
<rect x="765" y="535" width="60" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
|
||||||
|
<text x="795" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Cache</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Legend -->
|
||||||
|
<g id="legend" transform="translate(60, 600)">
|
||||||
|
<text x="0" y="0" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#1F2937">Key Concepts:</text>
|
||||||
|
|
||||||
|
<rect x="120" y="-12" width="15" height="15" fill="#D1FAE5" stroke="#10B981" stroke-width="1" rx="2"/>
|
||||||
|
<text x="140" y="0" font-family="Arial, sans-serif" font-size="11" fill="#4B5563">Virtual Crates = Modules in src/</text>
|
||||||
|
|
||||||
|
<rect x="320" y="-12" width="15" height="15" fill="#FEF3C7" stroke="#F59E0B" stroke-width="1" rx="2" stroke-dasharray="3,2"/>
|
||||||
|
<text x="340" y="0" font-family="Arial, sans-serif" font-size="11" fill="#4B5563">Your Contribution Space</text>
|
||||||
|
|
||||||
|
<text x="500" y="0" font-family="Arial, sans-serif" font-size="11" fill="#4B5563">All compile to single optimized binary</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Philosophy Note -->
|
||||||
|
<text x="450" y="650" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-style="italic" fill="#6B7280">gbapp virtual crates: The bridge between old Node.js packages and new Rust modules</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -9,7 +9,7 @@ This guide covers building BotServer from source, including dependencies, featur
|
||||||
- **Operating System**: Linux, macOS, or Windows
|
- **Operating System**: Linux, macOS, or Windows
|
||||||
- **Rust**: 1.70 or later (2021 edition)
|
- **Rust**: 1.70 or later (2021 edition)
|
||||||
- **Memory**: 4GB RAM minimum (8GB recommended)
|
- **Memory**: 4GB RAM minimum (8GB recommended)
|
||||||
- **Disk Space**: 2GB for dependencies and build artifacts
|
- **Disk Space**: 8GB for development environment
|
||||||
|
|
||||||
### Install Rust
|
### Install Rust
|
||||||
|
|
||||||
|
|
@ -412,6 +412,17 @@ Find duplicate dependencies:
|
||||||
cargo tree --duplicates
|
cargo tree --duplicates
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Security Audit
|
||||||
|
|
||||||
|
Run security audit to check for known vulnerabilities in dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo install cargo-audit
|
||||||
|
cargo audit
|
||||||
|
```
|
||||||
|
|
||||||
|
This should be run regularly during development to ensure dependencies are secure.
|
||||||
|
|
||||||
## Build Artifacts
|
## Build Artifacts
|
||||||
|
|
||||||
After a successful release build, you'll have:
|
After a successful release build, you'll have:
|
||||||
|
|
|
||||||
354
docs/src/chapter-07-gbapp/example-gbapp.md
Normal file
354
docs/src/chapter-07-gbapp/example-gbapp.md
Normal file
|
|
@ -0,0 +1,354 @@
|
||||||
|
# Example: Creating a New gbapp Virtual Crate
|
||||||
|
|
||||||
|
This guide walks through creating a new gbapp virtual crate called `analytics` that adds analytics capabilities to BotServer.
|
||||||
|
|
||||||
|
## Step 1: Create the Module Structure
|
||||||
|
|
||||||
|
Create your gbapp directory in `src/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
src/analytics/ # analytics.gbapp virtual crate
|
||||||
|
├── mod.rs # Module definition
|
||||||
|
├── keywords.rs # BASIC keywords
|
||||||
|
├── services.rs # Core functionality
|
||||||
|
├── models.rs # Data structures
|
||||||
|
└── tests.rs # Unit tests
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 2: Define the Module
|
||||||
|
|
||||||
|
**src/analytics/mod.rs**
|
||||||
|
```rust
|
||||||
|
//! Analytics gbapp - Provides analytics and reporting functionality
|
||||||
|
//!
|
||||||
|
//! This virtual crate adds analytics keywords to BASIC and provides
|
||||||
|
//! services for tracking and reporting bot interactions.
|
||||||
|
|
||||||
|
pub mod keywords;
|
||||||
|
pub mod services;
|
||||||
|
pub mod models;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
use crate::shared::state::AppState;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Initialize the analytics gbapp
|
||||||
|
pub fn init(state: Arc<AppState>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
log::info!("Initializing analytics.gbapp virtual crate");
|
||||||
|
|
||||||
|
// Initialize analytics services
|
||||||
|
services::init_analytics_service(&state)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 3: Add BASIC Keywords
|
||||||
|
|
||||||
|
**src/analytics/keywords.rs**
|
||||||
|
```rust
|
||||||
|
use crate::shared::state::AppState;
|
||||||
|
use rhai::{Engine, Dynamic};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Register analytics keywords with the BASIC interpreter
|
||||||
|
pub fn register_keywords(engine: &mut Engine, state: Arc<AppState>) {
|
||||||
|
let state_clone = state.clone();
|
||||||
|
|
||||||
|
// TRACK EVENT keyword
|
||||||
|
engine.register_fn("TRACK EVENT", move |event_name: String, properties: String| -> String {
|
||||||
|
let result = tokio::task::block_in_place(|| {
|
||||||
|
tokio::runtime::Handle::current().block_on(async {
|
||||||
|
crate::analytics::services::track_event(&state_clone, &event_name, &properties).await
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => format!("Event '{}' tracked", event_name),
|
||||||
|
Err(e) => format!("Failed to track event: {}", e),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// GET ANALYTICS keyword
|
||||||
|
engine.register_fn("GET ANALYTICS", move |metric: String, timeframe: String| -> Dynamic {
|
||||||
|
let result = tokio::task::block_in_place(|| {
|
||||||
|
tokio::runtime::Handle::current().block_on(async {
|
||||||
|
crate::analytics::services::get_analytics(&metric, &timeframe).await
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(data) => Dynamic::from(data),
|
||||||
|
Err(_) => Dynamic::UNIT,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// GENERATE REPORT keyword
|
||||||
|
engine.register_fn("GENERATE REPORT", move |report_type: String| -> String {
|
||||||
|
// Use LLM to generate natural language report
|
||||||
|
let data = crate::analytics::services::get_report_data(&report_type);
|
||||||
|
|
||||||
|
let prompt = format!(
|
||||||
|
"Generate a {} report from this data: {}",
|
||||||
|
report_type, data
|
||||||
|
);
|
||||||
|
|
||||||
|
// This would call the LLM service
|
||||||
|
format!("Report generated for: {}", report_type)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 4: Implement Services
|
||||||
|
|
||||||
|
**src/analytics/services.rs**
|
||||||
|
```rust
|
||||||
|
use crate::shared::state::AppState;
|
||||||
|
use crate::shared::models::AnalyticsEvent;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
/// Initialize analytics service
|
||||||
|
pub fn init_analytics_service(state: &Arc<AppState>) -> Result<()> {
|
||||||
|
// Set up database tables, connections, etc.
|
||||||
|
log::debug!("Analytics service initialized");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Track an analytics event
|
||||||
|
pub async fn track_event(
|
||||||
|
state: &Arc<AppState>,
|
||||||
|
event_name: &str,
|
||||||
|
properties: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
// Store event in database
|
||||||
|
let conn = state.conn.get()?;
|
||||||
|
|
||||||
|
// Implementation details...
|
||||||
|
log::debug!("Tracked event: {}", event_name);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get analytics data
|
||||||
|
pub async fn get_analytics(metric: &str, timeframe: &str) -> Result<String> {
|
||||||
|
// Query analytics data
|
||||||
|
let results = match metric {
|
||||||
|
"user_count" => get_user_count(timeframe).await?,
|
||||||
|
"message_volume" => get_message_volume(timeframe).await?,
|
||||||
|
"engagement_rate" => get_engagement_rate(timeframe).await?,
|
||||||
|
_ => return Err(anyhow::anyhow!("Unknown metric: {}", metric)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get data for report generation
|
||||||
|
pub fn get_report_data(report_type: &str) -> String {
|
||||||
|
// Gather data based on report type
|
||||||
|
match report_type {
|
||||||
|
"daily" => get_daily_report_data(),
|
||||||
|
"weekly" => get_weekly_report_data(),
|
||||||
|
"monthly" => get_monthly_report_data(),
|
||||||
|
_ => "{}".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
async fn get_user_count(timeframe: &str) -> Result<String> {
|
||||||
|
// Implementation
|
||||||
|
Ok("100".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_message_volume(timeframe: &str) -> Result<String> {
|
||||||
|
// Implementation
|
||||||
|
Ok("5000".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_engagement_rate(timeframe: &str) -> Result<String> {
|
||||||
|
// Implementation
|
||||||
|
Ok("75%".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_daily_report_data() -> String {
|
||||||
|
// Gather daily metrics
|
||||||
|
r#"{"users": 100, "messages": 1500, "sessions": 50}"#.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_weekly_report_data() -> String {
|
||||||
|
// Gather weekly metrics
|
||||||
|
r#"{"users": 500, "messages": 8000, "sessions": 300}"#.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_monthly_report_data() -> String {
|
||||||
|
// Gather monthly metrics
|
||||||
|
r#"{"users": 2000, "messages": 35000, "sessions": 1200}"#.to_string()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 5: Define Data Models
|
||||||
|
|
||||||
|
**src/analytics/models.rs**
|
||||||
|
```rust
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct AnalyticsEvent {
|
||||||
|
pub id: uuid::Uuid,
|
||||||
|
pub event_name: String,
|
||||||
|
pub properties: serde_json::Value,
|
||||||
|
pub user_id: Option<String>,
|
||||||
|
pub session_id: String,
|
||||||
|
pub timestamp: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct MetricSnapshot {
|
||||||
|
pub metric_name: String,
|
||||||
|
pub value: f64,
|
||||||
|
pub timestamp: DateTime<Utc>,
|
||||||
|
pub dimensions: serde_json::Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Report {
|
||||||
|
pub report_type: String,
|
||||||
|
pub generated_at: DateTime<Utc>,
|
||||||
|
pub data: serde_json::Value,
|
||||||
|
pub summary: String,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 6: Register with Core
|
||||||
|
|
||||||
|
Update `src/basic/keywords/mod.rs` to include your gbapp:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use crate::analytics;
|
||||||
|
|
||||||
|
pub fn register_all_keywords(engine: &mut Engine, state: Arc<AppState>) {
|
||||||
|
// ... existing keywords
|
||||||
|
|
||||||
|
// Register analytics.gbapp keywords
|
||||||
|
analytics::keywords::register_keywords(engine, state.clone());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Update `src/main.rs` or initialization code:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Initialize analytics gbapp
|
||||||
|
analytics::init(state.clone())?;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 7: Add Tests
|
||||||
|
|
||||||
|
**src/analytics/tests.rs**
|
||||||
|
```rust
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_track_event() {
|
||||||
|
// Test event tracking
|
||||||
|
let event_name = "user_login";
|
||||||
|
let properties = r#"{"user_id": "123"}"#;
|
||||||
|
|
||||||
|
// Test implementation
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_analytics() {
|
||||||
|
// Test analytics retrieval
|
||||||
|
let metric = "user_count";
|
||||||
|
let timeframe = "daily";
|
||||||
|
|
||||||
|
// Test implementation
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 8: Use in BASIC Scripts
|
||||||
|
|
||||||
|
Now your gbapp keywords are available in BASIC:
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' Track user actions
|
||||||
|
TRACK EVENT "button_clicked", "button=submit"
|
||||||
|
|
||||||
|
' Get metrics
|
||||||
|
daily_users = GET ANALYTICS "user_count", "daily"
|
||||||
|
TALK "Daily active users: " + daily_users
|
||||||
|
|
||||||
|
' Generate AI-powered report
|
||||||
|
report = GENERATE REPORT "weekly"
|
||||||
|
TALK report
|
||||||
|
|
||||||
|
' Combine with LLM for insights
|
||||||
|
metrics = GET ANALYTICS "all", "monthly"
|
||||||
|
insights = LLM "Analyze these metrics and provide insights: " + metrics
|
||||||
|
TALK insights
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 9: Add Feature Flag (Optional)
|
||||||
|
|
||||||
|
If your gbapp should be optional, add it to `Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
analytics = []
|
||||||
|
|
||||||
|
# Include in default features if always needed
|
||||||
|
default = ["ui-server", "chat", "analytics"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Then conditionally compile:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[cfg(feature = "analytics")]
|
||||||
|
pub mod analytics;
|
||||||
|
|
||||||
|
#[cfg(feature = "analytics")]
|
||||||
|
analytics::keywords::register_keywords(engine, state.clone());
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benefits of This Approach
|
||||||
|
|
||||||
|
1. **Clean Separation**: Your gbapp is self-contained
|
||||||
|
2. **Easy Discovery**: Visible in `src/analytics/`
|
||||||
|
3. **Type Safety**: Rust compiler checks everything
|
||||||
|
4. **Native Performance**: Compiles into the main binary
|
||||||
|
5. **Familiar Structure**: Like the old `.gbapp` packages
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
✅ **DO:**
|
||||||
|
- Keep your gbapp focused on one domain
|
||||||
|
- Provide clear BASIC keywords
|
||||||
|
- Use LLM for complex logic
|
||||||
|
- Write comprehensive tests
|
||||||
|
- Document your keywords
|
||||||
|
|
||||||
|
❌ **DON'T:**
|
||||||
|
- Create overly complex implementations
|
||||||
|
- Duplicate existing functionality
|
||||||
|
- Skip error handling
|
||||||
|
- Forget about async/await
|
||||||
|
- Ignore the BASIC-first philosophy
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Creating a gbapp virtual crate is straightforward:
|
||||||
|
1. Create a module in `src/`
|
||||||
|
2. Define keywords for BASIC
|
||||||
|
3. Implement services
|
||||||
|
4. Register with core
|
||||||
|
5. Use in BASIC scripts
|
||||||
|
|
||||||
|
Your gbapp becomes part of BotServer's compiled binary, providing native performance while maintaining the conceptual clarity of the package system. Most importantly, remember that the implementation should be minimal - let BASIC + LLM handle the complexity!
|
||||||
279
docs/src/chapter-07-gbapp/philosophy.md
Normal file
279
docs/src/chapter-07-gbapp/philosophy.md
Normal file
|
|
@ -0,0 +1,279 @@
|
||||||
|
# The gbapp Philosophy: Let Machines Do Machine Work
|
||||||
|
|
||||||
|
## Core Principle: Automation First
|
||||||
|
|
||||||
|
In 2025, the gbapp philosophy is simple and powerful:
|
||||||
|
|
||||||
|
**"If a machine can do the work, let it do the work."**
|
||||||
|
|
||||||
|
## The Hierarchy of Development
|
||||||
|
|
||||||
|
### 1. LLM First (90% of cases)
|
||||||
|
Let AI write the code for you:
|
||||||
|
```basic
|
||||||
|
' Don't write complex logic - describe what you want
|
||||||
|
result = LLM "Generate a function that validates email addresses and returns true/false: " + email
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. BASIC for Flow Control (9% of cases)
|
||||||
|
Use BASIC only for orchestration:
|
||||||
|
```basic
|
||||||
|
' BASIC is just glue between AI calls
|
||||||
|
data = GET "api/data"
|
||||||
|
processed = LLM "Process this: " + data
|
||||||
|
SET "results", processed
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Rust for Core Only (1% of cases)
|
||||||
|
Write Rust only when:
|
||||||
|
- Contributing new keywords to core
|
||||||
|
- Building fundamental infrastructure
|
||||||
|
- Optimizing critical performance paths
|
||||||
|
|
||||||
|
## What gbapp Really Is
|
||||||
|
|
||||||
|
**gbapp is NOT:**
|
||||||
|
- ❌ External plugin packages
|
||||||
|
- ❌ Separate npm modules
|
||||||
|
- ❌ A way to bypass BASIC
|
||||||
|
- ❌ Runtime extensions
|
||||||
|
|
||||||
|
**gbapp IS:**
|
||||||
|
- ✅ Virtual crates inside `src/`
|
||||||
|
- ✅ Rust modules that compile together
|
||||||
|
- ✅ The bridge between old and new thinking
|
||||||
|
- ✅ A familiar mental model for contributions
|
||||||
|
- ✅ A mindset: "Code through automation"
|
||||||
|
|
||||||
|
## Real-World Examples
|
||||||
|
|
||||||
|
### Wrong Approach (Old Thinking)
|
||||||
|
```javascript
|
||||||
|
// 500 lines of custom Node.js, Python or C# code for data validation
|
||||||
|
function validateComplexBusinessRules(data) {
|
||||||
|
// ... hundreds of lines of logic
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Right Approach (2025 Reality)
|
||||||
|
```basic
|
||||||
|
' 3 lines - let AI handle complexity
|
||||||
|
rules = GET "business-rules.txt"
|
||||||
|
validation = LLM "Validate this data against these rules: " + data + " Rules: " + rules
|
||||||
|
IF validation CONTAINS "valid" THEN TALK "Approved" ELSE TALK "Rejected: " + validation
|
||||||
|
```
|
||||||
|
|
||||||
|
## The Multi-SDK Reality
|
||||||
|
|
||||||
|
You don't need separate SDKs or plugins. Everything integrates through BASIC + LLM:
|
||||||
|
|
||||||
|
### Integrating Any API
|
||||||
|
```basic
|
||||||
|
' No SDK needed - just describe what you want
|
||||||
|
data = GET "https://server/data"
|
||||||
|
answer = LLM "Do a good report from this json: " + data
|
||||||
|
TALK data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Working with Any Database
|
||||||
|
```basic
|
||||||
|
' No ORM needed - AI understands SQL
|
||||||
|
results = FIND "users", "all users who logged in today"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Processing Any Format
|
||||||
|
```basic
|
||||||
|
' No parser library needed
|
||||||
|
xml_data = GET "complex.xml"
|
||||||
|
json = LLM "Convert this XML to JSON: " + xml_data
|
||||||
|
SET BOT MEMORY "processed_data", json
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Write Code
|
||||||
|
|
||||||
|
### Use LLM When:
|
||||||
|
- Processing unstructured data
|
||||||
|
- Implementing business logic
|
||||||
|
- Transforming between formats
|
||||||
|
- Making decisions
|
||||||
|
- Generating content
|
||||||
|
- Analyzing patterns
|
||||||
|
- **Basically: 90% of everything**
|
||||||
|
|
||||||
|
### Use BASIC When:
|
||||||
|
- Orchestrating AI calls
|
||||||
|
- Simple flow control
|
||||||
|
- Managing state
|
||||||
|
- Connecting systems
|
||||||
|
- **Just the glue**
|
||||||
|
|
||||||
|
### Use Rust When:
|
||||||
|
- Building new keywords in your gbapp virtual crate
|
||||||
|
- Creating a new gbapp module in `src/`
|
||||||
|
- System-level optimization
|
||||||
|
- Contributing new features as gbapps
|
||||||
|
- **Only for core enhancements**
|
||||||
|
|
||||||
|
## The gbapp Mindset
|
||||||
|
|
||||||
|
Stop thinking about:
|
||||||
|
- "How do I code this?"
|
||||||
|
- "What library do I need?"
|
||||||
|
- "How do I extend the system?"
|
||||||
|
|
||||||
|
Start thinking about:
|
||||||
|
- "How do I describe this to AI?"
|
||||||
|
- "What's the simplest BASIC flow?"
|
||||||
|
- "How does this help everyone?"
|
||||||
|
|
||||||
|
## Examples of Getting Real
|
||||||
|
|
||||||
|
### Data Enrichment (Old Way)
|
||||||
|
```javascript
|
||||||
|
// 1000+ lines of code
|
||||||
|
// Multiple NPM packages
|
||||||
|
// Complex error handling
|
||||||
|
// Maintenance nightmare
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data Enrichmentay)
|
||||||
|
```basic
|
||||||
|
items = FIND "companies", "needs_enrichment=true"
|
||||||
|
FOR EACH item IN items
|
||||||
|
website = WEBSITE OF item.company
|
||||||
|
page = GET website
|
||||||
|
enriched = LLM "Extract company info from: " + page
|
||||||
|
SET "companies", "id=" + item.id, "data=" + enriched
|
||||||
|
NEXT
|
||||||
|
```
|
||||||
|
|
||||||
|
### Report Generation (Old Way)
|
||||||
|
```python
|
||||||
|
# Custom reporting engine
|
||||||
|
# Template systems
|
||||||
|
# Complex formatting logic
|
||||||
|
# PDF libraries
|
||||||
|
```
|
||||||
|
|
||||||
|
### Report Generation (Get Real Way)
|
||||||
|
```basic
|
||||||
|
data = FIND "sales", "month=current"
|
||||||
|
report = LLM "Create executive summary from: " + data
|
||||||
|
CREATE SITE "report", "template", report
|
||||||
|
```
|
||||||
|
|
||||||
|
## The Ultimate Test
|
||||||
|
|
||||||
|
Before writing ANY code, ask yourself:
|
||||||
|
|
||||||
|
1. **Can LLM do this?** (Usually YES)
|
||||||
|
2. **Can BASIC orchestrate it?** (Almost always YES)
|
||||||
|
3. **Do I really need Rust?** (Almost never)
|
||||||
|
|
||||||
|
## Benefits of This Approach
|
||||||
|
|
||||||
|
### For Developers
|
||||||
|
- 100x faster development
|
||||||
|
- No dependency management
|
||||||
|
- No version conflicts
|
||||||
|
- No maintenance burden
|
||||||
|
- Focus on business logic, not implementation
|
||||||
|
|
||||||
|
### For Organizations
|
||||||
|
- Reduced complexity
|
||||||
|
- Lower maintenance costs
|
||||||
|
- Faster iterations
|
||||||
|
- No vendor lock-in
|
||||||
|
- Anyone can contribute
|
||||||
|
|
||||||
|
### For the Community
|
||||||
|
- Shared improvements benefit everyone
|
||||||
|
- No fragmentation
|
||||||
|
- Consistent experience
|
||||||
|
- Collective advancement
|
||||||
|
|
||||||
|
## The Future is Already Here
|
||||||
|
|
||||||
|
In 2025, this isn't aspirational - it's reality:
|
||||||
|
|
||||||
|
- **100% BASIC/LLM applications** are production-ready
|
||||||
|
- **Zero custom code** for most use cases
|
||||||
|
- **AI handles complexity** better than humans
|
||||||
|
- **Machines do machine work** while humans do human work
|
||||||
|
|
||||||
|
## Migration Path
|
||||||
|
|
||||||
|
### From Extensions to Virtual Crates
|
||||||
|
```
|
||||||
|
Old: node_modules/
|
||||||
|
└── my-plugin.gbapp/
|
||||||
|
├── index.js (500 lines)
|
||||||
|
├── package.json
|
||||||
|
└── complex logic
|
||||||
|
|
||||||
|
New: src/
|
||||||
|
└── my_feature/ # my_feature.gbapp (virtual crate)
|
||||||
|
├── mod.rs # 50 lines
|
||||||
|
└── keywords.rs # Register BASIC keywords
|
||||||
|
|
||||||
|
Plus: my-bot.gbdialog/
|
||||||
|
└── logic.bas (5 lines using LLM)
|
||||||
|
```
|
||||||
|
|
||||||
|
### From Code to Descriptions
|
||||||
|
```
|
||||||
|
Old: Write algorithm to process data
|
||||||
|
New: Describe what you want to LLM
|
||||||
|
```
|
||||||
|
|
||||||
|
### From Libraries to LLM
|
||||||
|
```
|
||||||
|
Old: Import 20 NPM packages
|
||||||
|
New: Single LLM call with description
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get Real Guidelines
|
||||||
|
|
||||||
|
✅ **DO:**
|
||||||
|
- Describe problems to LLM
|
||||||
|
- Use BASIC as glue
|
||||||
|
- Contribute keywords to core
|
||||||
|
- Share your patterns
|
||||||
|
- Think automation-first
|
||||||
|
|
||||||
|
❌ **DON'T:**
|
||||||
|
- Write complex algorithms
|
||||||
|
- Build separate plugins
|
||||||
|
- Create custom frameworks
|
||||||
|
- Maintain separate codebases
|
||||||
|
- Fight the machine
|
||||||
|
|
||||||
|
## The Virtual Crate Architecture
|
||||||
|
|
||||||
|
Each gbapp is now a module in `src/`:
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── core/ # core.gbapp
|
||||||
|
├── basic/ # basic.gbapp
|
||||||
|
├── channels/ # channels.gbapp
|
||||||
|
└── your_feature/ # your_feature.gbapp (your contribution!)
|
||||||
|
```
|
||||||
|
|
||||||
|
This elegant mapping preserves the conceptual model while leveraging Rust's power.
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
gbapp in 2025 has evolved from external packages to virtual crates - Rust modules inside `src/` that compile into a single, optimized binary. This preserves the familiar mental model while delivering native performance.
|
||||||
|
|
||||||
|
The philosophy remains: machines are better at machine work. Your job is to describe what you want, not implement how to do it. The combination of BASIC + LLM eliminates the need for traditional programming in almost all cases.
|
||||||
|
|
||||||
|
|
||||||
|
## Examples Repository
|
||||||
|
|
||||||
|
See `/templates/` for real-world examples of 100% BASIC/LLM applications:
|
||||||
|
- CRM system: 50 lines of BASIC
|
||||||
|
- Email automation: 30 lines of BASIC
|
||||||
|
- Data pipeline: 20 lines of BASIC
|
||||||
|
- Report generator: 15 lines of BASIC
|
||||||
|
|
||||||
|
Each would have been thousands of lines in traditional code.
|
||||||
|
|
@ -1,262 +1 @@
|
||||||
# Prompt Manager
|
# Prompt Manager
|
||||||
|
|
||||||
The Prompt Manager module provides centralized management of LLM prompts, templates, and system instructions used throughout BotServer.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Located in `src/prompt_manager/`, this module maintains a library of reusable prompts that can be:
|
|
||||||
- Versioned and updated without code changes
|
|
||||||
- Customized per bot instance
|
|
||||||
- Composed dynamically based on context
|
|
||||||
- Optimized for different LLM models
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
src/prompt_manager/
|
|
||||||
├── mod.rs # Main module interface
|
|
||||||
├── prompts.csv # Default prompt library
|
|
||||||
└── templates/ # Complex prompt templates
|
|
||||||
├── system.md # System instructions
|
|
||||||
├── tools.md # Tool-use prompts
|
|
||||||
└── context.md # Context formatting
|
|
||||||
```
|
|
||||||
|
|
||||||
## Prompt Library Format
|
|
||||||
|
|
||||||
The `prompts.csv` file stores prompts in a structured format:
|
|
||||||
|
|
||||||
```csv
|
|
||||||
id,category,name,content,model,version
|
|
||||||
1,system,default,"You are a helpful assistant...",gpt-4,1.0
|
|
||||||
2,tools,function_call,"To use a tool, follow this format...",any,1.0
|
|
||||||
3,context,kb_search,"Search the knowledge base for: {query}",any,1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fields
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
|-------|-------------|
|
|
||||||
| `id` | Unique identifier |
|
|
||||||
| `category` | Prompt category (system, tools, context, etc.) |
|
|
||||||
| `name` | Prompt name for retrieval |
|
|
||||||
| `content` | The actual prompt text with placeholders |
|
|
||||||
| `model` | Target model or "any" for universal |
|
|
||||||
| `version` | Version for tracking changes |
|
|
||||||
|
|
||||||
## Usage in BASIC
|
|
||||||
|
|
||||||
Prompts are automatically loaded and can be referenced in dialogs:
|
|
||||||
|
|
||||||
```basic
|
|
||||||
' For background processing only - not for interactive conversations
|
|
||||||
' Generate content for storage
|
|
||||||
summary = LLM "Use prompt: customer_service"
|
|
||||||
SET BOT MEMORY "service_info", summary
|
|
||||||
|
|
||||||
' For interactive conversations, use SET CONTEXT
|
|
||||||
SET CONTEXT "support_issue", issue
|
|
||||||
TALK "How can I help you with your technical issue?"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Rust API
|
|
||||||
|
|
||||||
### Loading Prompts
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use crate::prompt_manager::PromptManager;
|
|
||||||
|
|
||||||
let manager = PromptManager::new();
|
|
||||||
manager.load_from_csv("prompts.csv")?;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Retrieving Prompts
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// Get a specific prompt
|
|
||||||
let prompt = manager.get_prompt("system", "default")?;
|
|
||||||
|
|
||||||
// Get prompt with variable substitution
|
|
||||||
let mut vars = HashMap::new();
|
|
||||||
vars.insert("query", "user question");
|
|
||||||
let formatted = manager.format_prompt("context", "kb_search", vars)?;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dynamic Composition
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// Compose multiple prompts
|
|
||||||
let system = manager.get_prompt("system", "default")?;
|
|
||||||
let tools = manager.get_prompt("tools", "available")?;
|
|
||||||
let context = manager.get_prompt("context", "current")?;
|
|
||||||
|
|
||||||
let full_prompt = manager.compose(vec![system, tools, context])?;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Prompt Categories
|
|
||||||
|
|
||||||
### System Prompts
|
|
||||||
Define the AI assistant's role and behavior:
|
|
||||||
- `default`: Standard helpful assistant
|
|
||||||
- `professional`: Business-focused responses
|
|
||||||
- `technical`: Developer-oriented assistance
|
|
||||||
- `creative`: Creative writing and ideation
|
|
||||||
|
|
||||||
### Tool Prompts
|
|
||||||
Instructions for tool usage:
|
|
||||||
- `function_call`: How to invoke functions
|
|
||||||
- `parameter_format`: Parameter formatting rules
|
|
||||||
- `error_handling`: Tool error responses
|
|
||||||
|
|
||||||
### Context Prompts
|
|
||||||
Templates for providing context:
|
|
||||||
- `kb_search`: Knowledge base query format
|
|
||||||
- `conversation_history`: Previous message format
|
|
||||||
- `user_context`: User information format
|
|
||||||
|
|
||||||
### Guardrail Prompts
|
|
||||||
Safety and compliance instructions:
|
|
||||||
- `content_filter`: Inappropriate content handling
|
|
||||||
- `pii_protection`: Personal data protection
|
|
||||||
- `compliance`: Regulatory compliance rules
|
|
||||||
|
|
||||||
## Custom Prompts
|
|
||||||
|
|
||||||
Bots can override default prompts by providing their own:
|
|
||||||
|
|
||||||
```
|
|
||||||
mybot.gbai/
|
|
||||||
└── mybot.gbot/
|
|
||||||
├── config.csv
|
|
||||||
└── prompts.csv # Custom prompts override defaults
|
|
||||||
```
|
|
||||||
|
|
||||||
## Model-Specific Optimization
|
|
||||||
|
|
||||||
Prompts can be optimized for different models:
|
|
||||||
|
|
||||||
```csv
|
|
||||||
id,category,name,content,model,version
|
|
||||||
1,system,default,"You are Claude...",claude-3,1.0
|
|
||||||
2,system,default,"You are GPT-4...",gpt-4,1.0
|
|
||||||
3,system,default,"You are a helpful assistant",llama-3,1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
The manager automatically selects the best match for the current model.
|
|
||||||
|
|
||||||
## Variables and Placeholders
|
|
||||||
|
|
||||||
Prompts support variable substitution using `{variable}` syntax:
|
|
||||||
|
|
||||||
```
|
|
||||||
"Search for {query} in {collection} and return {limit} results"
|
|
||||||
```
|
|
||||||
|
|
||||||
Variables are replaced at runtime:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
let vars = hashmap!{
|
|
||||||
"query" => "pricing information",
|
|
||||||
"collection" => "docs",
|
|
||||||
"limit" => "5"
|
|
||||||
};
|
|
||||||
let prompt = manager.format_prompt("search", "template", vars)?;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Prompt Versioning
|
|
||||||
|
|
||||||
Track prompt evolution:
|
|
||||||
|
|
||||||
```csv
|
|
||||||
id,category,name,content,model,version
|
|
||||||
1,system,default,"Original prompt...",gpt-4,1.0
|
|
||||||
2,system,default,"Updated prompt...",gpt-4,1.1
|
|
||||||
3,system,default,"Latest prompt...",gpt-4,2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
The manager uses the latest version by default but can retrieve specific versions:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
let prompt = manager.get_prompt_version("system", "default", "1.0")?;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Performance Optimization
|
|
||||||
|
|
||||||
### Caching
|
|
||||||
Frequently used prompts are cached in memory:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
manager.cache_prompt("system", "default");
|
|
||||||
```
|
|
||||||
|
|
||||||
### Token Counting
|
|
||||||
Estimate token usage before sending:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
let tokens = manager.estimate_tokens(prompt, "gpt-4")?;
|
|
||||||
if tokens > MAX_TOKENS {
|
|
||||||
prompt = manager.compress_prompt(prompt, MAX_TOKENS)?;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compression
|
|
||||||
Automatically compress prompts while maintaining meaning:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
let compressed = manager.compress_prompt(original, target_tokens)?;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
1. **Modularity**: Keep prompts focused on single responsibilities
|
|
||||||
2. **Versioning**: Always version prompts for rollback capability
|
|
||||||
3. **Testing**: Test prompts across different models
|
|
||||||
4. **Documentation**: Document the purpose and expected output
|
|
||||||
5. **Variables**: Use placeholders for dynamic content
|
|
||||||
6. **Optimization**: Tailor prompts to specific model capabilities
|
|
||||||
|
|
||||||
## Integration with BASIC
|
|
||||||
|
|
||||||
The Prompt Manager is automatically available in BASIC dialogs:
|
|
||||||
|
|
||||||
```basic
|
|
||||||
' Load custom prompt library
|
|
||||||
LOAD_PROMPTS "custom_prompts.csv"
|
|
||||||
|
|
||||||
' For background processing - generate content once
|
|
||||||
greeting = LLM PROMPT("customer_greeting")
|
|
||||||
SET BOT MEMORY "standard_greeting", greeting
|
|
||||||
|
|
||||||
' For interactive conversations with variables
|
|
||||||
SET CONTEXT "customer_name", customer_name
|
|
||||||
SET CONTEXT "support_ticket", support_ticket
|
|
||||||
TALK "Let me help you with your support request."
|
|
||||||
```
|
|
||||||
|
|
||||||
## Monitoring and Analytics
|
|
||||||
|
|
||||||
Track prompt performance:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
// Log prompt usage
|
|
||||||
manager.log_usage("system", "default", response_quality);
|
|
||||||
|
|
||||||
// Get analytics
|
|
||||||
let stats = manager.get_prompt_stats("system", "default")?;
|
|
||||||
println!("Success rate: {}%", stats.success_rate);
|
|
||||||
println!("Avg response time: {}ms", stats.avg_latency);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Error Handling
|
|
||||||
|
|
||||||
Handle missing or invalid prompts gracefully:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
match manager.get_prompt("custom", "missing") {
|
|
||||||
Ok(prompt) => use_prompt(prompt),
|
|
||||||
Err(PromptError::NotFound) => use_default(),
|
|
||||||
Err(PromptError::Invalid) => log_and_fallback(),
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,111 @@
|
||||||
## gbot Reference
|
# Bot Configuration
|
||||||
`config.csv` defines the bot’s behaviour and parameters.
|
|
||||||
|
This chapter covers bot configuration through the `config.csv` file system. Each bot's behavior is controlled by a simple CSV configuration file in its `.gbot` package.
|
||||||
|
|
||||||
|
## Configuration System
|
||||||
|
|
||||||
|
BotServer uses a straightforward name-value CSV format for configuration:
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
# config.csv – Bot configuration
|
name,value
|
||||||
bot_name,GeneralBot
|
setting_name,setting_value
|
||||||
language,en
|
another_setting,another_value
|
||||||
theme,default.gbtheme
|
|
||||||
knowledge_base,default.gbkb
|
|
||||||
max_context_tokens,2048
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Key Columns
|
## File Location
|
||||||
- **bot_name** – Display name of the bot.
|
|
||||||
- **language** – Locale for formatting (used by `FORMAT`).
|
|
||||||
- **theme** – UI theme package (`.gbtheme`).
|
|
||||||
- **knowledge_base** – Default knowledge‑base package (`.gbkb`).
|
|
||||||
- **max_context_tokens** – Maximum number of tokens retained in the session context.
|
|
||||||
- **max_context_tokens** – Limit for the amount of context sent to the LLM.
|
|
||||||
|
|
||||||
### Editing the Configuration
|
```
|
||||||
The file is a simple CSV; each line is `key,value`. Comments start with `#`. After editing, restart the server to apply changes.
|
mybot.gbai/
|
||||||
|
└── mybot.gbot/
|
||||||
|
└── config.csv
|
||||||
|
```
|
||||||
|
|
||||||
### Runtime Effects
|
## Configuration Categories
|
||||||
- Changing **theme** updates the UI served from `web/static/`.
|
|
||||||
- Modifying **knowledge_base** switches the vector collection used for semantic search.
|
|
||||||
- Adjusting **answer_mode** influences the order of tool invocation and LLM calls.
|
|
||||||
|
|
||||||
For advanced configuration, see `src/bot/config.rs` which parses this file into the `BotConfig` struct.
|
### Server Settings
|
||||||
|
- Web server binding and ports
|
||||||
|
- Site generation paths
|
||||||
|
- Service endpoints
|
||||||
|
|
||||||
|
### LLM Configuration
|
||||||
|
- Model paths (local GGUF files)
|
||||||
|
- Service URLs
|
||||||
|
- Cache settings
|
||||||
|
- Server parameters (when embedded)
|
||||||
|
|
||||||
|
### Prompt Management
|
||||||
|
- Context compaction levels
|
||||||
|
- History retention
|
||||||
|
- Token management
|
||||||
|
|
||||||
|
### Email Integration
|
||||||
|
- SMTP server settings
|
||||||
|
- Authentication credentials
|
||||||
|
- Sender configuration
|
||||||
|
|
||||||
|
### Theme Customization
|
||||||
|
- Color schemes
|
||||||
|
- Logo URLs
|
||||||
|
- Bot titles
|
||||||
|
|
||||||
|
### Custom Database
|
||||||
|
- External database connections
|
||||||
|
- Authentication details
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
### Simple Format
|
||||||
|
- Plain CSV with name-value pairs
|
||||||
|
- No complex syntax
|
||||||
|
- Human-readable
|
||||||
|
|
||||||
|
### Flexible Structure
|
||||||
|
- Empty rows for visual grouping
|
||||||
|
- Optional settings with defaults
|
||||||
|
- Extensible for custom needs
|
||||||
|
|
||||||
|
### Local-First
|
||||||
|
- Designed for local LLM models
|
||||||
|
- Self-hosted services
|
||||||
|
- No cloud dependency by default
|
||||||
|
|
||||||
|
## Example Configurations
|
||||||
|
|
||||||
|
### Minimal Setup
|
||||||
|
Just the essentials to run a bot:
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
llm-url,http://localhost:8081
|
||||||
|
llm-model,../../../../data/llm/model.gguf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production Setup
|
||||||
|
Full configuration with all services:
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
,
|
||||||
|
server_host,0.0.0.0
|
||||||
|
server_port,8080
|
||||||
|
,
|
||||||
|
llm-url,http://localhost:8081
|
||||||
|
llm-model,../../../../data/llm/production-model.gguf
|
||||||
|
llm-cache,true
|
||||||
|
,
|
||||||
|
email-server,smtp.company.com
|
||||||
|
email-from,bot@company.com
|
||||||
|
,
|
||||||
|
theme-title,Company Assistant
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Philosophy
|
||||||
|
|
||||||
|
1. **Defaults Work**: Most settings have sensible defaults
|
||||||
|
2. **Local First**: Assumes local services, not cloud APIs
|
||||||
|
3. **Simple Values**: All values are strings, parsed as needed
|
||||||
|
4. **No Magic**: What you see is what you get
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [config.csv Reference](./config-csv.md) - Complete configuration options
|
- [config.csv Format](./config-csv.md) - Complete reference
|
||||||
- [PostgreSQL Setup](./postgresql.md) - Database configuration
|
- [LLM Configuration](./llm-config.md) - Language model settings
|
||||||
- [MinIO Storage](./minio.md) - Object storage setup
|
- [Parameters](./parameters.md) - All available parameters
|
||||||
- [Qdrant Vector DB](./qdrant.md) - Vector database configuration
|
|
||||||
- [Valkey Cache](./valkey.md) - Caching layer setup
|
|
||||||
- [Chapter 2: .gbot](../chapter-02/gbot.md) - Bot configuration package
|
|
||||||
- [Chapter 3: Knowledge Base](../chapter-03/README.md) - KB configuration
|
|
||||||
- [Chapter 5: BASIC Reference](../chapter-05/README.md) - Script configuration
|
|
||||||
- [Chapter 9: Storage](../chapter-09/storage.md) - Storage architecture
|
|
||||||
- [Chapter 11: Infrastructure](../chapter-11/README.md) - Complete infrastructure guide
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# Answer Modes
|
|
||||||
|
|
@ -1,263 +1,243 @@
|
||||||
# config.csv Format
|
# config.csv Format
|
||||||
|
|
||||||
The `config.csv` file is the central configuration for each bot instance. Located in the `.gbot` package directory, it controls all bot behavior, integrations, and system settings.
|
The `config.csv` file is the central configuration for each bot, located in the `.gbot` package. It uses a simple name-value pair format.
|
||||||
|
|
||||||
## File Location
|
## File Format
|
||||||
|
|
||||||
```
|
|
||||||
mybot.gbai/
|
|
||||||
└── mybot.gbot/
|
|
||||||
└── config.csv
|
|
||||||
```
|
|
||||||
|
|
||||||
## Format
|
|
||||||
|
|
||||||
Configuration uses simple CSV format with two columns: `key` and `value`.
|
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
key,value
|
name,value
|
||||||
botId,00000000-0000-0000-0000-000000000000
|
setting_name,setting_value
|
||||||
title,My Bot Name
|
another_setting,another_value
|
||||||
description,Bot description here
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Core Settings
|
- **Empty rows** are used for visual grouping
|
||||||
|
- **No quotes** needed for string values
|
||||||
|
- **Case-sensitive** names
|
||||||
|
|
||||||
### Bot Identity
|
## Core Server Settings
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `botId` | Unique bot identifier (UUID) | Generated | `00000000-0000-0000-0000-000000000000` |
|
|
||||||
| `title` | Bot display name | Required | `Customer Support Bot` |
|
|
||||||
| `description` | Bot description | Empty | `Handles customer inquiries` |
|
|
||||||
| `logoUrl` | Bot avatar/logo URL | Empty | `https://example.com/logo.png` |
|
|
||||||
| `welcomeMessage` | Initial greeting | Empty | `Hello! How can I help you today?` |
|
|
||||||
|
|
||||||
### LLM Configuration
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `llm-model` | Model path or name | Local model | `../../../../data/llm/model.gguf` |
|
|
||||||
| `llm-key` | API key (if using external) | `none` | `sk-...` for external APIs |
|
|
||||||
| `llm-url` | LLM endpoint URL | `http://localhost:8081` | Local or external endpoint |
|
|
||||||
| `llm-cache` | Enable LLM caching | `false` | `true` |
|
|
||||||
| `llm-cache-ttl` | Cache time-to-live (seconds) | `3600` | `7200` |
|
|
||||||
|
|
||||||
### Knowledge Base
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `qdrantUrl` | Vector database URL | `http://localhost:6333` | `http://qdrant:6333` |
|
|
||||||
| `qdrantApiKey` | Qdrant API key | Empty | `your-api-key` |
|
|
||||||
| `embeddingModel` | Model for embeddings | `text-embedding-ada-002` | `all-MiniLM-L6-v2` |
|
|
||||||
| `chunkSize` | Text chunk size | `1000` | `500` |
|
|
||||||
| `chunkOverlap` | Overlap between chunks | `200` | `100` |
|
|
||||||
| `topK` | Number of search results | `5` | `10` |
|
|
||||||
|
|
||||||
### Storage Configuration
|
|
||||||
### Server Configuration
|
### Server Configuration
|
||||||
|
```csv
|
||||||
| Key | Description | Default | Example |
|
server_host,0.0.0.0
|
||||||
|-----|-------------|---------|---------|
|
server_port,8080
|
||||||
| `server_host` | Server bind address | `0.0.0.0` | `localhost` |
|
sites_root,/tmp
|
||||||
| `server_port` | Server port | `8080` | `3000` |
|
|
||||||
| `sites_root` | Sites root directory | `/tmp` | `/var/www` |
|
|
||||||
| `mcp-server` | Enable MCP server | `false` | `true` |
|
|
||||||
|
|
||||||
### Database
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `databaseUrl` | PostgreSQL connection | Required | `postgresql://user:pass@localhost/botdb` |
|
|
||||||
| `maxConnections` | Connection pool size | `10` | `25` |
|
|
||||||
| `connectionTimeout` | Timeout in seconds | `30` | `60` |
|
|
||||||
|
|
||||||
### Email Integration
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `smtpHost` | SMTP server | Empty | `smtp.gmail.com` |
|
|
||||||
| `smtpPort` | SMTP port | `587` | `465` |
|
|
||||||
| `smtpUser` | Email username | Empty | `bot@example.com` |
|
|
||||||
| `smtpPassword` | Email password | Empty | `app-specific-password` |
|
|
||||||
| `smtpFrom` | From address | Empty | `noreply@example.com` |
|
|
||||||
| `smtpUseTls` | Use TLS | `true` | `false` |
|
|
||||||
|
|
||||||
### Calendar Integration
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `calendarEnabled` | Enable calendar features | `false` | `true` |
|
|
||||||
| `calendarProvider` | Calendar service | `google` | `microsoft`, `caldav` |
|
|
||||||
| `calendarApiKey` | Calendar API key | Empty | `your-api-key` |
|
|
||||||
| `workingHoursStart` | Business hours start | `09:00` | `08:30` |
|
|
||||||
| `workingHoursEnd` | Business hours end | `17:00` | `18:00` |
|
|
||||||
| `timezone` | Default timezone | `UTC` | `America/New_York` |
|
|
||||||
|
|
||||||
### Authentication
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `authEnabled` | Require authentication | `false` | `true` |
|
|
||||||
| `authProvider` | Auth provider | `local` | `oauth`, `saml`, `ldap` |
|
|
||||||
| `authClientId` | OAuth client ID | Empty | `client-id` |
|
|
||||||
| `authClientSecret` | OAuth secret | Empty | `client-secret` |
|
|
||||||
| `authCallbackUrl` | OAuth callback | Empty | `https://bot.example.com/auth/callback` |
|
|
||||||
| `jwtSecret` | JWT signing secret | Generated | `your-secret-key` |
|
|
||||||
| `sessionTimeout` | Session duration (min) | `1440` | `60` |
|
|
||||||
|
|
||||||
### Channel Configuration
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `webEnabled` | Enable web interface | `true` | `false` |
|
|
||||||
| `whatsappEnabled` | Enable WhatsApp | `false` | `true` |
|
|
||||||
| `whatsappToken` | WhatsApp API token | Empty | `EAAI...` |
|
|
||||||
| `whatsappPhoneId` | WhatsApp phone ID | Empty | `123456789` |
|
|
||||||
| `teamsEnabled` | Enable MS Teams | `false` | `true` |
|
|
||||||
| `teamsAppId` | Teams app ID | Empty | `app-id` |
|
|
||||||
| `teamsAppPassword` | Teams app password | Empty | `app-password` |
|
|
||||||
| `slackEnabled` | Enable Slack | `false` | `true` |
|
|
||||||
| `slackToken` | Slack bot token | Empty | `xoxb-...` |
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `corsOrigins` | Allowed CORS origins | `*` | `https://example.com` |
|
|
||||||
| `rateLimitPerMinute` | API rate limit | `60` | `100` |
|
|
||||||
| `maxFileSize` | Max upload size (MB) | `10` | `50` |
|
|
||||||
| `allowedFileTypes` | Permitted file types | `pdf,doc,txt` | `*` |
|
|
||||||
| `encryptionKey` | Data encryption key | Generated | `base64-key` |
|
|
||||||
| `requireHttps` | Force HTTPS | `false` | `true` |
|
|
||||||
|
|
||||||
### Monitoring
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `metricsEnabled` | Enable metrics | `false` | `true` |
|
|
||||||
| `metricsEndpoint` | Metrics endpoint | `/metrics` | `/admin/metrics` |
|
|
||||||
| `loggingLevel` | Log level | `info` | `debug`, `warn`, `error` |
|
|
||||||
| `logToFile` | Log to file | `false` | `true` |
|
|
||||||
| `logFilePath` | Log file location | `./logs` | `/var/log/botserver` |
|
|
||||||
| `sentryDsn` | Sentry error tracking | Empty | `https://...@sentry.io/...` |
|
|
||||||
|
|
||||||
### Advanced Features
|
|
||||||
|
|
||||||
| Key | Description | Default | Example |
|
|
||||||
|-----|-------------|---------|---------|
|
|
||||||
| `webAutomationEnabled` | Enable web scraping | `false` | `true` |
|
|
||||||
| `ocrEnabled` | Enable OCR | `false` | `true` |
|
|
||||||
| `speechEnabled` | Enable speech | `false` | `true` |
|
|
||||||
| `translationEnabled` | Enable translation | `false` | `true` |
|
|
||||||
| `cacheEnabled` | Enable cache component | `false` | `true` |
|
|
||||||
| `cacheUrl` | Cache URL | `redis://localhost:6379` | `redis://cache:6379` |
|
|
||||||
|
|
||||||
## Environment Variable Override
|
|
||||||
|
|
||||||
Any config value can be overridden using environment variables:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Override LLM model
|
|
||||||
export BOT_LLM_MODEL=gpt-4-turbo
|
|
||||||
|
|
||||||
# Override database URL
|
|
||||||
export BOT_DATABASE_URL=postgresql://prod@db/botserver
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Multiple Bots Configuration
|
| Name | Description | Default | Example |
|
||||||
|
|------|-------------|---------|---------|
|
||||||
|
| `server_host` | Bind address for the web server | `0.0.0.0` | `0.0.0.0` |
|
||||||
|
| `server_port` | Port for the web interface | `8080` | `8080` |
|
||||||
|
| `sites_root` | Directory for generated sites | `/tmp` | `/tmp` |
|
||||||
|
|
||||||
Each bot has its own `config.csv`. The system loads all bot configurations on startup:
|
## LLM Configuration
|
||||||
|
|
||||||
```
|
### LLM Connection
|
||||||
templates/
|
```csv
|
||||||
├── support.gbai/
|
llm-key,none
|
||||||
│ └── support.gbot/
|
llm-url,http://localhost:8081
|
||||||
│ └── config.csv # Support bot config
|
llm-model,../../../../data/llm/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf
|
||||||
├── sales.gbai/
|
|
||||||
│ └── sales.gbot/
|
|
||||||
│ └── config.csv # Sales bot config
|
|
||||||
└── default.gbai/
|
|
||||||
└── default.gbot/
|
|
||||||
└── config.csv # Default bot config
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration Validation
|
| Name | Description | Default | Example |
|
||||||
|
|------|-------------|---------|---------|
|
||||||
|
| `llm-key` | API key for LLM service | `none` | `none` or API key |
|
||||||
|
| `llm-url` | LLM service endpoint | `http://localhost:8081` | `http://localhost:8081` |
|
||||||
|
| `llm-model` | Path to GGUF model file | Model path | `../../../../data/llm/model.gguf` |
|
||||||
|
|
||||||
The system validates configuration on startup:
|
### LLM Cache Settings
|
||||||
- Required fields must be present
|
```csv
|
||||||
- UUIDs must be valid format
|
llm-cache,false
|
||||||
- URLs must be reachable
|
llm-cache-ttl,3600
|
||||||
- API keys are tested
|
llm-cache-semantic,true
|
||||||
- File paths must exist
|
llm-cache-threshold,0.95
|
||||||
|
```
|
||||||
|
|
||||||
## Hot Reload
|
| Name | Description | Default | Example |
|
||||||
|
|------|-------------|---------|---------|
|
||||||
|
| `llm-cache` | Enable response caching | `false` | `true` or `false` |
|
||||||
|
| `llm-cache-ttl` | Cache TTL in seconds | `3600` | `3600` |
|
||||||
|
| `llm-cache-semantic` | Enable semantic similarity caching | `true` | `true` or `false` |
|
||||||
|
| `llm-cache-threshold` | Similarity threshold (0-1) | `0.95` | `0.95` |
|
||||||
|
|
||||||
Changes to `config.csv` can be reloaded without restart:
|
### LLM Server Settings (when running embedded)
|
||||||
1. Edit the file
|
```csv
|
||||||
2. Call `/api/admin/reload-config` endpoint
|
llm-server,false
|
||||||
3. Or use the admin UI reload button
|
llm-server-path,botserver-stack/bin/llm/build/bin
|
||||||
|
llm-server-host,0.0.0.0
|
||||||
|
llm-server-port,8081
|
||||||
|
llm-server-gpu-layers,0
|
||||||
|
llm-server-n-moe,0
|
||||||
|
llm-server-ctx-size,4096
|
||||||
|
llm-server-n-predict,1024
|
||||||
|
llm-server-parallel,6
|
||||||
|
llm-server-cont-batching,true
|
||||||
|
llm-server-mlock,false
|
||||||
|
llm-server-no-mmap,false
|
||||||
|
```
|
||||||
|
|
||||||
## Security Best Practices
|
| Name | Description | Default |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| `llm-server` | Run embedded LLM server | `false` |
|
||||||
|
| `llm-server-path` | Path to LLM server binaries | `botserver-stack/bin/llm/build/bin` |
|
||||||
|
| `llm-server-host` | LLM server bind address | `0.0.0.0` |
|
||||||
|
| `llm-server-port` | LLM server port | `8081` |
|
||||||
|
| `llm-server-gpu-layers` | GPU layers to offload | `0` |
|
||||||
|
| `llm-server-n-moe` | Number of MoE experts | `0` |
|
||||||
|
| `llm-server-ctx-size` | Context size in tokens | `4096` |
|
||||||
|
| `llm-server-n-predict` | Max prediction tokens | `1024` |
|
||||||
|
| `llm-server-parallel` | Parallel requests | `6` |
|
||||||
|
| `llm-server-cont-batching` | Continuous batching | `true` |
|
||||||
|
| `llm-server-mlock` | Lock model in memory | `false` |
|
||||||
|
| `llm-server-no-mmap` | Disable memory mapping | `false` |
|
||||||
|
|
||||||
1. **Never commit API keys** - Use environment variables
|
## Prompt Settings
|
||||||
2. **Encrypt sensitive values** - Use `encryptionKey` setting
|
|
||||||
3. **Rotate credentials regularly** - Update keys monthly
|
|
||||||
4. **Use strong JWT secrets** - At least 32 characters
|
|
||||||
5. **Restrict CORS origins** - Don't use `*` in production
|
|
||||||
6. **Enable HTTPS** - Set `requireHttps=true`
|
|
||||||
7. **Set rate limits** - Prevent abuse
|
|
||||||
8. **Monitor access** - Enable logging and metrics
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Bot Won't Start
|
|
||||||
- Check required fields are set
|
|
||||||
- Verify database connection
|
|
||||||
- Ensure bot ID is unique
|
|
||||||
|
|
||||||
### LLM Not Responding
|
|
||||||
- Verify API key is valid
|
|
||||||
- Check endpoint URL
|
|
||||||
- Test rate limits
|
|
||||||
|
|
||||||
### Storage Issues
|
|
||||||
- Verify drive is running
|
|
||||||
- Check access credentials
|
|
||||||
- Test bucket permissions
|
|
||||||
|
|
||||||
### Authentication Problems
|
|
||||||
- Verify JWT secret matches
|
|
||||||
- Check session timeout
|
|
||||||
- Test OAuth callback URL
|
|
||||||
|
|
||||||
## Example Configuration
|
|
||||||
|
|
||||||
Complete example for a production bot:
|
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
key,value
|
prompt-compact,4
|
||||||
botId,a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
prompt-history,2
|
||||||
title,Customer Support Assistant
|
|
||||||
description,24/7 automated customer support
|
|
||||||
welcomeMessage,Hello! I'm here to help with any questions.
|
|
||||||
llmModel,gpt-4
|
|
||||||
llmApiKey,${LLM_API_KEY}
|
|
||||||
llmTemperature,0.3
|
|
||||||
databaseUrl,${DATABASE_URL}
|
|
||||||
minioEndpoint,storage.example.com
|
|
||||||
minioAccessKey,${MINIO_ACCESS}
|
|
||||||
minioSecretKey,${MINIO_SECRET}
|
|
||||||
minioBucket,support-bot
|
|
||||||
minioUseSsl,true
|
|
||||||
authEnabled,true
|
|
||||||
authProvider,oauth
|
|
||||||
authClientId,${OAUTH_CLIENT_ID}
|
|
||||||
authClientSecret,${OAUTH_CLIENT_SECRET}
|
|
||||||
corsOrigins,https://app.example.com
|
|
||||||
requireHttps,true
|
|
||||||
loggingLevel,info
|
|
||||||
metricsEnabled,true
|
|
||||||
cacheEnabled,true
|
|
||||||
cacheUrl,redis://cache:6379
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
| Name | Description | Default | Example |
|
||||||
|
|------|-------------|---------|---------|
|
||||||
|
| `prompt-compact` | Context compaction level | `4` | `4` |
|
||||||
|
| `prompt-history` | Messages to keep in history | Not set | `2` |
|
||||||
|
|
||||||
|
## Embedding Configuration
|
||||||
|
|
||||||
|
```csv
|
||||||
|
embedding-url,http://localhost:8082
|
||||||
|
embedding-model,../../../../data/llm/bge-small-en-v1.5-f32.gguf
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Description | Default |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| `embedding-url` | Embedding service endpoint | `http://localhost:8082` |
|
||||||
|
| `embedding-model` | Path to embedding model | Model path |
|
||||||
|
|
||||||
|
## Email Configuration
|
||||||
|
|
||||||
|
```csv
|
||||||
|
email-from,from@domain.com
|
||||||
|
email-server,mail.domain.com
|
||||||
|
email-port,587
|
||||||
|
email-user,user@domain.com
|
||||||
|
email-pass,
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Description | Example |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| `email-from` | Sender email address | `noreply@example.com` |
|
||||||
|
| `email-server` | SMTP server hostname | `smtp.gmail.com` |
|
||||||
|
| `email-port` | SMTP port | `587` |
|
||||||
|
| `email-user` | SMTP username | `user@example.com` |
|
||||||
|
| `email-pass` | SMTP password | Password (empty if not set) |
|
||||||
|
|
||||||
|
## Theme Configuration
|
||||||
|
|
||||||
|
```csv
|
||||||
|
theme-color1,#0d2b55
|
||||||
|
theme-color2,#fff9c2
|
||||||
|
theme-logo,https://pragmatismo.com.br/icons/general-bots.svg
|
||||||
|
theme-title,Announcements General Bots
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Description | Example |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| `theme-color1` | Primary theme color | `#0d2b55` |
|
||||||
|
| `theme-color2` | Secondary theme color | `#fff9c2` |
|
||||||
|
| `theme-logo` | Logo URL | `https://example.com/logo.svg` |
|
||||||
|
| `theme-title` | Bot display title | `My Bot` |
|
||||||
|
|
||||||
|
## Custom Database
|
||||||
|
|
||||||
|
```csv
|
||||||
|
custom-server,localhost
|
||||||
|
custom-port,5432
|
||||||
|
custom-database,mycustomdb
|
||||||
|
custom-username,
|
||||||
|
custom-password,
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Description | Example |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| `custom-server` | Database server | `localhost` |
|
||||||
|
| `custom-port` | Database port | `5432` |
|
||||||
|
| `custom-database` | Database name | `mydb` |
|
||||||
|
| `custom-username` | Database user | Username |
|
||||||
|
| `custom-password` | Database password | Password |
|
||||||
|
|
||||||
|
## MCP Server
|
||||||
|
|
||||||
|
```csv
|
||||||
|
mcp-server,false
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Description | Default |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| `mcp-server` | Enable MCP server | `false` |
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
### Minimal Configuration
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
server_port,8080
|
||||||
|
llm-url,http://localhost:8081
|
||||||
|
llm-model,../../../../data/llm/model.gguf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production Configuration
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
,
|
||||||
|
server_host,0.0.0.0
|
||||||
|
server_port,443
|
||||||
|
sites_root,/var/www/sites
|
||||||
|
,
|
||||||
|
llm-key,sk-...
|
||||||
|
llm-url,https://api.openai.com
|
||||||
|
llm-model,gpt-4
|
||||||
|
,
|
||||||
|
llm-cache,true
|
||||||
|
llm-cache-ttl,7200
|
||||||
|
,
|
||||||
|
email-from,bot@company.com
|
||||||
|
email-server,smtp.company.com
|
||||||
|
email-port,587
|
||||||
|
email-user,bot@company.com
|
||||||
|
email-pass,secure_password
|
||||||
|
,
|
||||||
|
theme-title,Company Assistant
|
||||||
|
theme-color1,#003366
|
||||||
|
theme-color2,#ffffff
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Loading
|
||||||
|
|
||||||
|
1. Default values are applied first
|
||||||
|
2. `config.csv` values override defaults
|
||||||
|
3. Environment variables override config.csv (if implemented)
|
||||||
|
4. All values are strings - parsed as needed by the application
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
✅ **DO:**
|
||||||
|
- Group related settings with empty rows
|
||||||
|
- Use descriptive values
|
||||||
|
- Keep sensitive data in environment variables when possible
|
||||||
|
- Test configuration changes in development first
|
||||||
|
|
||||||
|
❌ **DON'T:**
|
||||||
|
- Include quotes around values
|
||||||
|
- Use spaces around commas
|
||||||
|
- Leave trailing commas
|
||||||
|
- Include comments with # (use empty name field instead)
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
The system validates:
|
||||||
|
- Required fields are present
|
||||||
|
- Port numbers are valid (1-65535)
|
||||||
|
- URLs are properly formatted
|
||||||
|
- File paths exist (for model files)
|
||||||
|
- Email settings are complete if email features are used
|
||||||
|
|
@ -1,16 +1,10 @@
|
||||||
# LLM Configuration
|
# LLM Configuration
|
||||||
|
|
||||||
Configure Large Language Model providers for bot conversations. BotServer prioritizes local models for privacy and cost-effectiveness.
|
Configuration for Language Model integration in BotServer, supporting both local GGUF models and external API services.
|
||||||
|
|
||||||
## Overview
|
## Local Model Configuration
|
||||||
|
|
||||||
BotServer supports both local models (GGUF format) and cloud APIs. The default configuration uses local models running on your hardware.
|
BotServer is designed to work with local GGUF models by default:
|
||||||
|
|
||||||
## Local Models (Default)
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
From `default.gbai/default.gbot/config.csv`:
|
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
llm-key,none
|
llm-key,none
|
||||||
|
|
@ -18,13 +12,35 @@ llm-url,http://localhost:8081
|
||||||
llm-model,../../../../data/llm/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf
|
llm-model,../../../../data/llm/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf
|
||||||
```
|
```
|
||||||
|
|
||||||
### LLM Server Settings
|
### Model Path
|
||||||
|
|
||||||
|
The `llm-model` parameter accepts:
|
||||||
|
- **Relative paths**: `../../../../data/llm/model.gguf`
|
||||||
|
- **Absolute paths**: `/opt/models/model.gguf`
|
||||||
|
- **Model names**: When using external APIs like `gpt-4`
|
||||||
|
|
||||||
|
### Supported Model Formats
|
||||||
|
|
||||||
|
- **GGUF**: Quantized models for CPU/GPU inference
|
||||||
|
- **Q3_K_M, Q4_K_M, Q5_K_M**: Different quantization levels
|
||||||
|
- **F16, F32**: Full precision models
|
||||||
|
|
||||||
|
## LLM Server Configuration
|
||||||
|
|
||||||
|
### Running Embedded Server
|
||||||
|
|
||||||
|
BotServer can run its own LLM server:
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
llm-server,false
|
llm-server,true
|
||||||
llm-server-path,botserver-stack/bin/llm/build/bin
|
llm-server-path,botserver-stack/bin/llm/build/bin
|
||||||
llm-server-host,0.0.0.0
|
llm-server-host,0.0.0.0
|
||||||
llm-server-port,8081
|
llm-server-port,8081
|
||||||
|
```
|
||||||
|
|
||||||
|
### Server Performance Parameters
|
||||||
|
|
||||||
|
```csv
|
||||||
llm-server-gpu-layers,0
|
llm-server-gpu-layers,0
|
||||||
llm-server-ctx-size,4096
|
llm-server-ctx-size,4096
|
||||||
llm-server-n-predict,1024
|
llm-server-n-predict,1024
|
||||||
|
|
@ -32,136 +48,174 @@ llm-server-parallel,6
|
||||||
llm-server-cont-batching,true
|
llm-server-cont-batching,true
|
||||||
```
|
```
|
||||||
|
|
||||||
### Supported Local Models
|
| Parameter | Description | Impact |
|
||||||
|
|-----------|-------------|---------|
|
||||||
|
| `llm-server-gpu-layers` | Layers to offload to GPU | 0 = CPU only, higher = more GPU |
|
||||||
|
| `llm-server-ctx-size` | Context window size | More context = more memory |
|
||||||
|
| `llm-server-n-predict` | Max tokens to generate | Limits response length |
|
||||||
|
| `llm-server-parallel` | Concurrent requests | Higher = more throughput |
|
||||||
|
| `llm-server-cont-batching` | Continuous batching | Improves multi-user performance |
|
||||||
|
|
||||||
- **DeepSeek-R1-Distill-Qwen** - Efficient reasoning model
|
### Memory Management
|
||||||
- **Llama-3** - Open source, high quality
|
|
||||||
- **Mistral** - Fast and capable
|
|
||||||
- **Phi-3** - Microsoft's small but powerful model
|
|
||||||
- **Qwen** - Multilingual support
|
|
||||||
|
|
||||||
### GPU Acceleration
|
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
llm-server-gpu-layers,33 # Number of layers to offload to GPU
|
llm-server-mlock,false
|
||||||
|
llm-server-no-mmap,false
|
||||||
```
|
```
|
||||||
|
|
||||||
Set to 0 for CPU-only operation.
|
- **mlock**: Locks model in RAM (prevents swapping)
|
||||||
|
- **no-mmap**: Disables memory mapping (uses more RAM)
|
||||||
|
|
||||||
## Embeddings Configuration
|
## Cache Configuration
|
||||||
|
|
||||||
For semantic search and vector operations:
|
### Basic Cache Settings
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
embedding-url,http://localhost:8082
|
llm-cache,false
|
||||||
embedding-model,../../../../data/llm/bge-small-en-v1.5-f32.gguf
|
|
||||||
```
|
|
||||||
|
|
||||||
## Caching Configuration
|
|
||||||
|
|
||||||
Reduce latency and costs with intelligent caching:
|
|
||||||
|
|
||||||
```csv
|
|
||||||
llm-cache,true
|
|
||||||
llm-cache-ttl,3600
|
llm-cache-ttl,3600
|
||||||
|
```
|
||||||
|
|
||||||
|
Caching reduces repeated LLM calls for identical inputs.
|
||||||
|
|
||||||
|
### Semantic Cache
|
||||||
|
|
||||||
|
```csv
|
||||||
llm-cache-semantic,true
|
llm-cache-semantic,true
|
||||||
llm-cache-threshold,0.95
|
llm-cache-threshold,0.95
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cloud Providers (Optional)
|
Semantic caching matches similar (not just identical) queries:
|
||||||
|
- **threshold**: 0.95 = 95% similarity required
|
||||||
|
- Lower threshold = more cache hits but less accuracy
|
||||||
|
|
||||||
### External API Configuration
|
## External API Configuration
|
||||||
|
|
||||||
For cloud LLM services, configure:
|
### OpenAI-Compatible APIs
|
||||||
|
|
||||||
```csv
|
```csv
|
||||||
llm-key,your-api-key
|
llm-key,sk-your-api-key
|
||||||
llm-url,https://api.provider.com/v1
|
llm-url,https://api.openai.com/v1
|
||||||
llm-model,model-name
|
llm-model,gpt-4
|
||||||
```
|
```
|
||||||
|
|
||||||
### Provider Examples
|
### Local API Servers
|
||||||
|
|
||||||
| Provider | URL | Model Examples |
|
```csv
|
||||||
|----------|-----|----------------|
|
llm-key,none
|
||||||
| Local | http://localhost:8081 | GGUF models |
|
llm-url,http://localhost:8081
|
||||||
| API Compatible | Various | Various models |
|
llm-model,local-model-name
|
||||||
| Custom | Your endpoint | Your models |
|
```
|
||||||
|
|
||||||
|
## Configuration Examples
|
||||||
|
|
||||||
|
### Minimal Local Setup
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
llm-url,http://localhost:8081
|
||||||
|
llm-model,../../../../data/llm/model.gguf
|
||||||
|
```
|
||||||
|
|
||||||
|
### High-Performance Local
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
llm-server,true
|
||||||
|
llm-server-gpu-layers,32
|
||||||
|
llm-server-ctx-size,8192
|
||||||
|
llm-server-parallel,8
|
||||||
|
llm-server-cont-batching,true
|
||||||
|
llm-cache,true
|
||||||
|
llm-cache-semantic,true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Low-Resource Setup
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
llm-server-ctx-size,2048
|
||||||
|
llm-server-n-predict,512
|
||||||
|
llm-server-parallel,2
|
||||||
|
llm-cache,false
|
||||||
|
llm-server-mlock,false
|
||||||
|
```
|
||||||
|
|
||||||
|
### External API
|
||||||
|
```csv
|
||||||
|
name,value
|
||||||
|
llm-key,sk-...
|
||||||
|
llm-url,https://api.anthropic.com
|
||||||
|
llm-model,claude-3
|
||||||
|
llm-cache,true
|
||||||
|
llm-cache-ttl,7200
|
||||||
|
```
|
||||||
|
|
||||||
## Performance Tuning
|
## Performance Tuning
|
||||||
|
|
||||||
### Context Size
|
### For Responsiveness
|
||||||
|
- Decrease `llm-server-ctx-size`
|
||||||
|
- Decrease `llm-server-n-predict`
|
||||||
|
- Enable `llm-cache`
|
||||||
|
- Enable `llm-cache-semantic`
|
||||||
|
|
||||||
```csv
|
### For Quality
|
||||||
llm-server-ctx-size,4096 # Maximum context window
|
- Increase `llm-server-ctx-size`
|
||||||
prompt-compact,4 # Compact after N exchanges
|
- Increase `llm-server-n-predict`
|
||||||
```
|
- Use higher quantization (Q5_K_M or F16)
|
||||||
|
- Disable semantic cache or increase threshold
|
||||||
|
|
||||||
### Parallel Processing
|
### For Multiple Users
|
||||||
|
- Enable `llm-server-cont-batching`
|
||||||
|
- Increase `llm-server-parallel`
|
||||||
|
- Enable caching
|
||||||
|
- Consider GPU offloading
|
||||||
|
|
||||||
```csv
|
## Model Selection Guidelines
|
||||||
llm-server-parallel,6 # Concurrent requests
|
|
||||||
llm-server-cont-batching,true # Continuous batching
|
|
||||||
```
|
|
||||||
|
|
||||||
### Memory Settings
|
### Small Models (1-3B parameters)
|
||||||
|
- Fast responses
|
||||||
|
- Low memory usage
|
||||||
|
- Good for simple tasks
|
||||||
|
- Example: `DeepSeek-R1-Distill-Qwen-1.5B`
|
||||||
|
|
||||||
```csv
|
### Medium Models (7-13B parameters)
|
||||||
llm-server-mlock,false # Lock model in memory
|
- Balanced performance
|
||||||
llm-server-no-mmap,false # Disable memory mapping
|
- Moderate memory usage
|
||||||
```
|
- Good general purpose
|
||||||
|
- Example: `Llama-2-7B`, `Mistral-7B`
|
||||||
|
|
||||||
## Model Selection Guide
|
### Large Models (30B+ parameters)
|
||||||
|
- Best quality
|
||||||
| Use Case | Recommended Model | Configuration |
|
- High memory requirements
|
||||||
|----------|------------------|---------------|
|
- Complex reasoning
|
||||||
| General chat | DeepSeek-R1-Distill | Default config |
|
- Example: `Llama-2-70B`, `Mixtral-8x7B`
|
||||||
| Code assistance | Qwen-Coder | Increase context |
|
|
||||||
| Multilingual | Qwen-Multilingual | Add language params |
|
|
||||||
| Fast responses | Phi-3-mini | Reduce predict tokens |
|
|
||||||
| High accuracy | Llama-3-70B | Increase GPU layers |
|
|
||||||
|
|
||||||
## Monitoring
|
|
||||||
|
|
||||||
Check LLM server status:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl http://localhost:8081/health
|
|
||||||
```
|
|
||||||
|
|
||||||
View model information:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl http://localhost:8081/v1/models
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Model Not Loading
|
### Model Won't Load
|
||||||
|
- Check file path exists
|
||||||
1. Check file path is correct
|
- Verify sufficient RAM
|
||||||
2. Verify GGUF format
|
- Ensure compatible GGUF version
|
||||||
3. Ensure sufficient memory
|
|
||||||
4. Check GPU drivers (if using GPU)
|
|
||||||
|
|
||||||
### Slow Responses
|
### Slow Responses
|
||||||
|
- Reduce context size
|
||||||
|
- Enable caching
|
||||||
|
- Use GPU offloading
|
||||||
|
- Choose smaller model
|
||||||
|
|
||||||
1. Reduce context size
|
### Out of Memory
|
||||||
2. Enable GPU acceleration
|
- Reduce `llm-server-ctx-size`
|
||||||
3. Use smaller model
|
- Reduce `llm-server-parallel`
|
||||||
4. Enable caching
|
- Use more quantized model (Q3 instead of Q5)
|
||||||
|
- Disable `llm-server-mlock`
|
||||||
|
|
||||||
### High Memory Usage
|
### Connection Refused
|
||||||
|
- Verify `llm-server` is true
|
||||||
1. Use quantized models (Q4, Q5)
|
- Check port not in use
|
||||||
2. Reduce batch size
|
- Ensure firewall allows connection
|
||||||
3. Enable memory mapping
|
|
||||||
4. Lower context size
|
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
1. **Start with local models** - Better privacy and no API costs
|
1. **Start Small**: Begin with small models and scale up
|
||||||
2. **Use appropriate model size** - Balance quality vs speed
|
2. **Use Caching**: Enable for production deployments
|
||||||
3. **Enable caching** - Reduce redundant computations
|
3. **Monitor Memory**: Watch RAM usage during operation
|
||||||
4. **Monitor resources** - Watch CPU/GPU/memory usage
|
4. **Test Thoroughly**: Verify responses before production
|
||||||
5. **Test different models** - Find the best fit for your use case
|
5. **Document Models**: Keep notes on model performance
|
||||||
|
6. **Version Control**: Track config.csv changes
|
||||||
|
|
@ -1,295 +1,188 @@
|
||||||
# Bot Parameters
|
# Configuration Parameters
|
||||||
|
|
||||||
Comprehensive reference for all bot configuration parameters available in `config.csv`.
|
Complete reference of all available parameters in `config.csv`.
|
||||||
|
|
||||||
## Parameter Categories
|
## Server Parameters
|
||||||
|
|
||||||
Bot parameters are organized into functional groups for easier management and understanding.
|
### Web Server
|
||||||
|
| Parameter | Description | Default | Type |
|
||||||
|
|-----------|-------------|---------|------|
|
||||||
|
| `server_host` | Server bind address | `0.0.0.0` | IP address |
|
||||||
|
| `server_port` | Server listen port | `8080` | Number (1-65535) |
|
||||||
|
| `sites_root` | Generated sites directory | `/tmp` | Path |
|
||||||
|
|
||||||
## Core Bot Settings
|
### MCP Server
|
||||||
|
| Parameter | Description | Default | Type |
|
||||||
### Identity Parameters
|
|-----------|-------------|---------|------|
|
||||||
|
| `mcp-server` | Enable MCP protocol server | `false` | Boolean |
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `botId` | UUID | Yes | Generated | Unique bot identifier |
|
|
||||||
| `title` | String | Yes | None | Bot display name |
|
|
||||||
| `description` | String | No | Empty | Bot description |
|
|
||||||
| `version` | String | No | "1.0" | Bot version |
|
|
||||||
| `author` | String | No | Empty | Bot creator |
|
|
||||||
| `language` | String | No | "en" | Default language |
|
|
||||||
| `timezone` | String | No | "UTC" | Bot timezone |
|
|
||||||
|
|
||||||
### Behavior Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `welcomeMessage` | String | No | Empty | Initial greeting |
|
|
||||||
| `fallbackMessage` | String | No | "I don't understand" | Default error response |
|
|
||||||
| `goodbyeMessage` | String | No | "Goodbye!" | Session end message |
|
|
||||||
| `typingDelay` | Number | No | 1000 | Typing indicator delay (ms) |
|
|
||||||
| `responseTimeout` | Number | No | 30000 | Response timeout (ms) |
|
|
||||||
| `maxRetries` | Number | No | 3 | Maximum retry attempts |
|
|
||||||
| `debugMode` | Boolean | No | false | Enable debug logging |
|
|
||||||
|
|
||||||
## LLM Parameters
|
## LLM Parameters
|
||||||
|
|
||||||
### Model Configuration
|
### Core LLM Settings
|
||||||
|
| Parameter | Description | Default | Type |
|
||||||
|
|-----------|-------------|---------|------|
|
||||||
|
| `llm-key` | API key for LLM service | `none` | String |
|
||||||
|
| `llm-url` | LLM service endpoint | `http://localhost:8081` | URL |
|
||||||
|
| `llm-model` | Model path or identifier | Required | Path/String |
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
### LLM Cache
|
||||||
|-----------|------|----------|---------|-------------|
|
| Parameter | Description | Default | Type |
|
||||||
| `llmProvider` | String | Yes | "openai" | LLM provider (openai, anthropic, google, local) |
|
|-----------|-------------|---------|------|
|
||||||
| `llmModel` | String | Yes | "gpt-4" | Model name |
|
| `llm-cache` | Enable response caching | `false` | Boolean |
|
||||||
| `llmApiKey` | String | Yes* | None | API key (*not required for local) |
|
| `llm-cache-ttl` | Cache time-to-live | `3600` | Seconds |
|
||||||
| `llmEndpoint` | String | No | Provider default | Custom API endpoint |
|
| `llm-cache-semantic` | Semantic similarity cache | `true` | Boolean |
|
||||||
| `llmOrganization` | String | No | Empty | Organization ID (OpenAI) |
|
| `llm-cache-threshold` | Similarity threshold | `0.95` | Float (0-1) |
|
||||||
| `llmProject` | String | No | Empty | Project ID (Google) |
|
|
||||||
|
|
||||||
### Response Control
|
### Embedded LLM Server
|
||||||
|
| Parameter | Description | Default | Type |
|
||||||
|
|-----------|-------------|---------|------|
|
||||||
|
| `llm-server` | Run embedded server | `false` | Boolean |
|
||||||
|
| `llm-server-path` | Server binary path | `botserver-stack/bin/llm/build/bin` | Path |
|
||||||
|
| `llm-server-host` | Server bind address | `0.0.0.0` | IP address |
|
||||||
|
| `llm-server-port` | Server port | `8081` | Number |
|
||||||
|
| `llm-server-gpu-layers` | GPU offload layers | `0` | Number |
|
||||||
|
| `llm-server-n-moe` | MoE experts count | `0` | Number |
|
||||||
|
| `llm-server-ctx-size` | Context size | `4096` | Tokens |
|
||||||
|
| `llm-server-n-predict` | Max predictions | `1024` | Tokens |
|
||||||
|
| `llm-server-parallel` | Parallel requests | `6` | Number |
|
||||||
|
| `llm-server-cont-batching` | Continuous batching | `true` | Boolean |
|
||||||
|
| `llm-server-mlock` | Lock in memory | `false` | Boolean |
|
||||||
|
| `llm-server-no-mmap` | Disable mmap | `false` | Boolean |
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
## Embedding Parameters
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `llmTemperature` | Float | No | 0.7 | Creativity (0.0-1.0) |
|
|
||||||
| `llmMaxTokens` | Number | No | 2000 | Max response tokens |
|
|
||||||
| `llmTopP` | Float | No | 1.0 | Nucleus sampling |
|
|
||||||
| `llmFrequencyPenalty` | Float | No | 0.0 | Reduce repetition |
|
|
||||||
| `llmPresencePenalty` | Float | No | 0.0 | Encourage new topics |
|
|
||||||
| `llmStopSequences` | String | No | Empty | Stop generation sequences |
|
|
||||||
| `llmSystemPrompt` | String | No | Default | System instruction |
|
|
||||||
|
|
||||||
### Cost Management
|
| Parameter | Description | Default | Type |
|
||||||
|
|-----------|-------------|---------|------|
|
||||||
|
| `embedding-url` | Embedding service endpoint | `http://localhost:8082` | URL |
|
||||||
|
| `embedding-model` | Embedding model path | Required for KB | Path |
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
## Prompt Parameters
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `llmCostLimit` | Number | No | 100 | Monthly cost limit ($) |
|
|
||||||
| `llmTokenLimit` | Number | No | 1000000 | Monthly token limit |
|
|
||||||
| `llmRequestLimit` | Number | No | 10000 | Daily request limit |
|
|
||||||
| `llmCacheEnabled` | Boolean | No | true | Enable response caching |
|
|
||||||
| `llmCacheTTL` | Number | No | 3600 | Cache duration (seconds) |
|
|
||||||
|
|
||||||
## Knowledge Base Parameters
|
| Parameter | Description | Default | Type |
|
||||||
|
|-----------|-------------|---------|------|
|
||||||
|
| `prompt-compact` | Context compaction level | `4` | Number |
|
||||||
|
| `prompt-history` | Messages in history | Not set | Number |
|
||||||
|
|
||||||
### Vector Database
|
## Email Parameters
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
| Parameter | Description | Default | Type |
|
||||||
|-----------|------|----------|---------|-------------|
|
|-----------|-------------|---------|------|
|
||||||
| `vectorDbUrl` | String | No | "http://localhost:6333" | Qdrant URL |
|
| `email-from` | Sender address | Required for email | Email |
|
||||||
| `vectorDbApiKey` | String | No | Empty | Qdrant API key |
|
| `email-server` | SMTP hostname | Required for email | Hostname |
|
||||||
| `vectorDbCollection` | String | No | Bot name | Default collection |
|
| `email-port` | SMTP port | `587` | Number |
|
||||||
| `embeddingModel` | String | No | "text-embedding-ada-002" | Embedding model |
|
| `email-user` | SMTP username | Required for email | String |
|
||||||
| `embeddingDimension` | Number | No | 1536 | Vector dimension |
|
| `email-pass` | SMTP password | Required for email | String |
|
||||||
|
|
||||||
### Search Configuration
|
## Theme Parameters
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
| Parameter | Description | Default | Type |
|
||||||
|-----------|------|----------|---------|-------------|
|
|-----------|-------------|---------|------|
|
||||||
| `searchTopK` | Number | No | 5 | Results to return |
|
| `theme-color1` | Primary color | Not set | Hex color |
|
||||||
| `searchThreshold` | Float | No | 0.7 | Minimum similarity |
|
| `theme-color2` | Secondary color | Not set | Hex color |
|
||||||
| `searchRerank` | Boolean | No | false | Enable reranking |
|
| `theme-logo` | Logo URL | Not set | URL |
|
||||||
| `chunkSize` | Number | No | 1000 | Text chunk size |
|
| `theme-title` | Bot display title | Not set | String |
|
||||||
| `chunkOverlap` | Number | No | 200 | Chunk overlap |
|
|
||||||
|
|
||||||
## Storage Parameters
|
## Custom Database Parameters
|
||||||
|
|
||||||
### Object Storage
|
| Parameter | Description | Default | Type |
|
||||||
|
|-----------|-------------|---------|------|
|
||||||
|
| `custom-server` | Database server | `localhost` | Hostname |
|
||||||
|
| `custom-port` | Database port | `5432` | Number |
|
||||||
|
| `custom-database` | Database name | Not set | String |
|
||||||
|
| `custom-username` | Database user | Not set | String |
|
||||||
|
| `custom-password` | Database password | Not set | String |
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
## Parameter Types
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `storageProvider` | String | No | "drive" | Storage provider |
|
|
||||||
| `storageEndpoint` | String | Yes | "localhost:9000" | S3-compatible drive endpoint |
|
|
||||||
| `storageAccessKey` | String | Yes | None | Access key |
|
|
||||||
| `storageSecretKey` | String | Yes | None | Secret key |
|
|
||||||
| `storageBucket` | String | No | "botserver" | Default bucket |
|
|
||||||
| `storageRegion` | String | No | "us-east-1" | AWS region |
|
|
||||||
| `storageUseSsl` | Boolean | No | false | Use HTTPS |
|
|
||||||
|
|
||||||
### File Handling
|
### Boolean
|
||||||
|
Values: `true` or `false` (case-sensitive)
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
### Number
|
||||||
|-----------|------|----------|---------|-------------|
|
Integer values, must be within valid ranges:
|
||||||
| `maxFileSize` | Number | No | 10 | Max file size (MB) |
|
- Ports: 1-65535
|
||||||
| `allowedFileTypes` | String | No | "pdf,doc,txt,csv" | Allowed extensions |
|
- Tokens: Positive integers
|
||||||
| `fileRetention` | Number | No | 90 | Days to keep files |
|
- Percentages: 0-100
|
||||||
| `autoDeleteTemp` | Boolean | No | true | Auto-delete temp files |
|
|
||||||
|
|
||||||
## Communication Parameters
|
### Float
|
||||||
|
Decimal values:
|
||||||
|
- Thresholds: 0.0 to 1.0
|
||||||
|
|
||||||
### Email Settings
|
### Path
|
||||||
|
File system paths:
|
||||||
|
- Relative: `../../../../data/model.gguf`
|
||||||
|
- Absolute: `/opt/models/model.gguf`
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
### URL
|
||||||
|-----------|------|----------|---------|-------------|
|
Valid URLs:
|
||||||
| `emailEnabled` | Boolean | No | false | Enable email |
|
- HTTP: `http://localhost:8081`
|
||||||
| `smtpHost` | String | No* | Empty | SMTP server |
|
- HTTPS: `https://api.example.com`
|
||||||
| `smtpPort` | Number | No | 587 | SMTP port |
|
|
||||||
| `smtpUser` | String | No* | Empty | Email username |
|
|
||||||
| `smtpPassword` | String | No* | Empty | Email password |
|
|
||||||
| `smtpFrom` | String | No* | Empty | From address |
|
|
||||||
| `smtpUseTls` | Boolean | No | true | Use TLS |
|
|
||||||
| `smtpUseStarttls` | Boolean | No | true | Use STARTTLS |
|
|
||||||
|
|
||||||
### Channel Configuration
|
### String
|
||||||
|
Any text value (no quotes needed in CSV)
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
### Email
|
||||||
|-----------|------|----------|---------|-------------|
|
Valid email format: `user@domain.com`
|
||||||
| `webEnabled` | Boolean | No | true | Web interface |
|
|
||||||
| `webPort` | Number | No | 8080 | Web port |
|
|
||||||
| `whatsappEnabled` | Boolean | No | false | WhatsApp integration |
|
|
||||||
| `whatsappToken` | String | No* | Empty | WhatsApp token |
|
|
||||||
| `teamsEnabled` | Boolean | No | false | Teams integration |
|
|
||||||
| `teamsAppId` | String | No* | Empty | Teams app ID |
|
|
||||||
| `slackEnabled` | Boolean | No | false | Slack integration |
|
|
||||||
| `slackToken` | String | No* | Empty | Slack token |
|
|
||||||
|
|
||||||
## Security Parameters
|
### Hex Color
|
||||||
|
HTML color codes: `#RRGGBB` format
|
||||||
|
|
||||||
### Authentication
|
## Required vs Optional
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
### Always Required
|
||||||
|-----------|------|----------|---------|-------------|
|
- None - all parameters have defaults or are optional
|
||||||
| `authRequired` | Boolean | No | false | Require authentication |
|
|
||||||
| `authProvider` | String | No | "local" | Auth provider |
|
|
||||||
| `jwtSecret` | String | Yes* | Generated | JWT secret |
|
|
||||||
| `jwtExpiration` | Number | No | 86400 | Token expiration (s) |
|
|
||||||
| `sessionTimeout` | Number | No | 3600 | Session timeout (s) |
|
|
||||||
| `maxSessions` | Number | No | 100 | Max concurrent sessions |
|
|
||||||
|
|
||||||
### Access Control
|
### Required for Features
|
||||||
|
- **LLM**: `llm-model` must be set
|
||||||
|
- **Email**: `email-from`, `email-server`, `email-user`
|
||||||
|
- **Embeddings**: `embedding-model` for knowledge base
|
||||||
|
- **Custom DB**: `custom-database` if using external database
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
## Configuration Precedence
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `corsOrigins` | String | No | "*" | Allowed origins |
|
|
||||||
| `ipWhitelist` | String | No | Empty | Allowed IPs |
|
|
||||||
| `ipBlacklist` | String | No | Empty | Blocked IPs |
|
|
||||||
| `rateLimitPerMinute` | Number | No | 60 | Requests per minute |
|
|
||||||
| `rateLimitPerHour` | Number | No | 1000 | Requests per hour |
|
|
||||||
| `requireHttps` | Boolean | No | false | Force HTTPS |
|
|
||||||
|
|
||||||
### Data Protection
|
1. **Built-in defaults** (hardcoded)
|
||||||
|
2. **config.csv values** (override defaults)
|
||||||
|
3. **Environment variables** (if implemented, override config)
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
## Special Values
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `encryptData` | Boolean | No | true | Encrypt stored data |
|
|
||||||
| `encryptionKey` | String | Yes* | Generated | Encryption key |
|
|
||||||
| `maskPii` | Boolean | No | true | Mask personal data |
|
|
||||||
| `auditLogging` | Boolean | No | true | Enable audit logs |
|
|
||||||
| `dataRetention` | Number | No | 365 | Data retention (days) |
|
|
||||||
|
|
||||||
## Performance Parameters
|
- `none` - Explicitly no value (for `llm-key`)
|
||||||
|
- Empty string - Unset/use default
|
||||||
|
- `false` - Feature disabled
|
||||||
|
- `true` - Feature enabled
|
||||||
|
|
||||||
### Caching
|
## Performance Tuning
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
### For Local Models
|
||||||
|-----------|------|----------|---------|-------------|
|
```csv
|
||||||
| `cacheEnabled` | Boolean | No | true | Enable caching |
|
llm-server-ctx-size,8192
|
||||||
| `cacheProvider` | String | No | "cache" | Cache provider |
|
llm-server-n-predict,2048
|
||||||
| `cacheUrl` | String | No | "redis://localhost:6379" | Cache URL |
|
llm-server-parallel,4
|
||||||
| `cacheTtl` | Number | No | 3600 | Default TTL (s) |
|
llm-cache,true
|
||||||
| `cacheMaxSize` | Number | No | 100 | Max cache size (MB) |
|
llm-cache-ttl,7200
|
||||||
|
|
||||||
### Resource Limits
|
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `maxCpu` | Number | No | 2 | CPU cores limit |
|
|
||||||
| `maxMemory` | Number | No | 2048 | Memory limit (MB) |
|
|
||||||
| `maxConnections` | Number | No | 100 | DB connections |
|
|
||||||
| `maxWorkers` | Number | No | 4 | Worker threads |
|
|
||||||
| `queueSize` | Number | No | 1000 | Task queue size |
|
|
||||||
|
|
||||||
## Monitoring Parameters
|
|
||||||
|
|
||||||
### Logging
|
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `logLevel` | String | No | "info" | Log level |
|
|
||||||
| `logToFile` | Boolean | No | true | Log to file |
|
|
||||||
| `logFilePath` | String | No | "./logs" | Log directory |
|
|
||||||
| `logRotation` | String | No | "daily" | Rotation schedule |
|
|
||||||
| `logRetention` | Number | No | 30 | Keep logs (days) |
|
|
||||||
|
|
||||||
### Metrics
|
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `metricsEnabled` | Boolean | No | false | Enable metrics |
|
|
||||||
| `metricsEndpoint` | String | No | "/metrics" | Metrics endpoint |
|
|
||||||
| `sentryDsn` | String | No | Empty | Sentry DSN |
|
|
||||||
| `datadogApiKey` | String | No | Empty | Datadog API key |
|
|
||||||
| `prometheusPort` | Number | No | 9090 | Prometheus port |
|
|
||||||
|
|
||||||
## Feature Flags
|
|
||||||
|
|
||||||
### Experimental Features
|
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `betaFeatures` | Boolean | No | false | Enable beta features |
|
|
||||||
| `webAutomation` | Boolean | No | false | Web scraping |
|
|
||||||
| `ocrEnabled` | Boolean | No | false | OCR support |
|
|
||||||
| `speechEnabled` | Boolean | No | false | Speech I/O |
|
|
||||||
| `visionEnabled` | Boolean | No | false | Image analysis |
|
|
||||||
| `codeExecution` | Boolean | No | false | Code running |
|
|
||||||
|
|
||||||
## Environment-Specific Parameters
|
|
||||||
|
|
||||||
### Development
|
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `devMode` | Boolean | No | false | Development mode |
|
|
||||||
| `hotReload` | Boolean | No | false | Hot reload |
|
|
||||||
| `mockServices` | Boolean | No | false | Use mock services |
|
|
||||||
| `verboseErrors` | Boolean | No | false | Detailed errors |
|
|
||||||
|
|
||||||
### Production
|
|
||||||
|
|
||||||
| Parameter | Type | Required | Default | Description |
|
|
||||||
|-----------|------|----------|---------|-------------|
|
|
||||||
| `prodMode` | Boolean | No | true | Production mode |
|
|
||||||
| `clustering` | Boolean | No | false | Enable clustering |
|
|
||||||
| `loadBalancing` | Boolean | No | false | Load balancing |
|
|
||||||
| `autoScale` | Boolean | No | false | Auto-scaling |
|
|
||||||
|
|
||||||
## Parameter Validation
|
|
||||||
|
|
||||||
Parameters are validated on startup:
|
|
||||||
1. Required parameters must be present
|
|
||||||
2. Types are checked and coerced
|
|
||||||
3. Ranges are enforced
|
|
||||||
4. Dependencies verified
|
|
||||||
5. Conflicts detected
|
|
||||||
|
|
||||||
## Environment Variable Override
|
|
||||||
|
|
||||||
Any parameter can be overridden via environment:
|
|
||||||
```bash
|
|
||||||
BOT_TITLE="My Bot" BOT_LLM_MODEL="gpt-4-turbo" botserver
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dynamic Parameter Updates
|
### For Production
|
||||||
|
```csv
|
||||||
Some parameters can be updated at runtime:
|
llm-server-cont-batching,true
|
||||||
- Log level
|
llm-cache-semantic,true
|
||||||
- Rate limits
|
llm-cache-threshold,0.90
|
||||||
- Cache settings
|
llm-server-parallel,8
|
||||||
- Feature flags
|
|
||||||
|
|
||||||
Use the admin API to update:
|
|
||||||
```
|
|
||||||
POST /api/admin/config
|
|
||||||
{
|
|
||||||
"logLevel": "debug",
|
|
||||||
"rateLimitPerMinute": 120
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Best Practices
|
### For Low Memory
|
||||||
|
```csv
|
||||||
|
llm-server-ctx-size,2048
|
||||||
|
llm-server-n-predict,512
|
||||||
|
llm-server-mlock,false
|
||||||
|
llm-server-no-mmap,false
|
||||||
|
llm-cache,false
|
||||||
|
```
|
||||||
|
|
||||||
1. **Start with defaults**: Most parameters have sensible defaults
|
## Validation Rules
|
||||||
2. **Override only what's needed**: Don't set everything
|
|
||||||
3. **Use environment variables**: For sensitive values
|
1. **Paths**: Model files must exist
|
||||||
4. **Document custom values**: Explain why changed
|
2. **URLs**: Must be valid format
|
||||||
5. **Test configuration**: Validate before production
|
3. **Ports**: Must be 1-65535
|
||||||
6. **Monitor performance**: Adjust based on metrics
|
4. **Emails**: Must contain @ and domain
|
||||||
7. **Version control**: Track configuration changes
|
5. **Colors**: Must be valid hex format
|
||||||
|
6. **Booleans**: Exactly `true` or `false`
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue