A stateful, rule-based, and similarity-based customer support chatbot developed with PHP and Laravel for Internet Service Provider (ISP) customer support operations.
The chatbot analyzes user messages using text similarity algorithms, identifies the most relevant intent and conversation category, manages multi-step conversations through session-based state management, and communicates with external ISS/OIM APIs to retrieve customer information and perform operational actions.
The system is designed to go beyond static chatbot responses by supporting dynamic conversation flows, customer personalization, external API integrations, payment operations, connection diagnostics, field-failure tickets, and dynamic internet plan selection.
Arda Baran
Computer Engineer
- About the Project
- Key Features
- Technology Stack
- Architecture
- Request Processing Flow
- Project Structure
- Core Services
- ChatbotService
- DecisionTree
- TextSimilarityService
- Conversation State Management
- State Design Pattern
- BotAuthInfo
- OIM Integration
- CustomerOverviewService
- ISS API Integration
- DecisionActions
- Dynamic Plan Selection
- Knowledge Base
- Conversation Nodes
- Action Status Mapping
- Action Text Parser
- API Endpoints
- Example Usage
- Example Conversation
- Response Structure
- Installation
- Environment Configuration
- Security
- Performance
- Testing
- Design Decisions
- Adding a New Intent
- Adding a New Action
- Adding a New Conversation State
- Error Handling
- Future Improvements
- Development Architecture
- Author
- License
This project is a customer support chatbot designed to automate common support operations for an Internet Service Provider.
Instead of relying only on static responses, the system analyzes each user message, identifies the most relevant conversation category, determines the appropriate conversation node, maintains the current state of the conversation, and performs backend operations when necessary.
For example, when a user sends:
I don't have internet access
the request can follow a flow similar to:
User Message
│
▼
ChatbotController
│
▼
ChatbotService
│
▼
DecisionTree
│
▼
TextSimilarityService
│
▼
Internet Problem Category
│
▼
ConversationState
│
▼
DecisionActions
│
▼
ISS / OIM API
│
▼
Dynamic Response
This architecture allows the chatbot to:
- Understand different variations of the same user intent
- Handle spelling mistakes and typing errors
- Normalize Turkish characters and punctuation
- Maintain multi-step conversations
- Store temporary conversation data
- Retrieve customer information from OIM
- Check internet connection status
- Check payment and debt information
- Retrieve payment links
- Create field-failure tickets
- Retrieve current internet plan information
- Retrieve available plans
- Submit plan change requests
- Generate dynamic conversation branches
- Personalize responses using customer information
The user's message does not have to exactly match a predefined trigger.
For example, the following messages can potentially be mapped to the same category:
Internetim yok
İnternete bağlanamıyorum
internte baglantim yok
The system uses multiple similarity techniques to determine how closely the user's message matches predefined intent triggers.
Conversation flows are represented as a decision tree.
A simplified example:
Internet Problem
│
├── PPP Session Check
│
├── Connection Check
│
├── Troubleshooting
│
└── Field Failure
This allows conversation logic to be maintained independently from the application code.
The chatbot supports multi-step conversations instead of treating every message as an independent request.
For example:
Bot:
Please enter your subscriber number.
User:
12345678
Bot:
I'm checking your connection...
The chatbot knows that 12345678 belongs to the currently active conversation flow because the conversation state is stored in the Laravel session.
Customer information can be retrieved from OIM and used to personalize chatbot responses.
For example:
Dear customer Arda, I am checking your internet connection.
The personalization layer is implemented through:
GetCustomerInfoFromOIM
The chatbot integrates with external ISP and OIM services for real operational data.
Supported operations include:
- Authentication
- Customer information retrieval
- PPP session checks
- Connection history
- Payment information
- Payment links
- Field-failure ticket creation
- Internet plan information
- Available plan retrieval
- Plan change requests
| Technology | Purpose |
|---|---|
| PHP | Primary programming language |
| Laravel | Backend framework |
| Guzzle | HTTP/API communication |
| JSON | Knowledge base and conversation definitions |
| Laravel Session | Conversation and authentication state |
| REST API | ISS/OIM integration |
| Decision Tree | Conversation flow management |
| Levenshtein | Character-level similarity |
similar_text() |
General text similarity |
| Cosine Similarity | Word-frequency similarity |
The project follows a service-oriented backend architecture.
High-level architecture:
┌─────────────────────┐
│ Client │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ ChatbotController │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ ChatbotService │
└──────┬───────┬──────┘
│ │
┌──────────────┘ └──────────────┐
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ DecisionTree │ │ ConversationState│
└────────┬────────┘ └──────────────────┘
│
▼
┌─────────────────────┐
│TextSimilarityService│
└─────────────────────┘
ChatbotService
│
▼
┌─────────────────┐
│ DecisionActions │
└───────┬─────────┘
│
┌─────────┴──────────┐
▼ ▼
ISS API OIM API
The general request lifecycle is:
User Message
│
▼
ChatbotController
│
▼
ChatbotService::reply()
│
├── Is there an active conversation state?
│ │
│ ├── Yes → handleNode()
│ │
│ └── No
│
▼
Customer Personalization
│
▼
DecisionTree::matchCategory()
│
▼
TextSimilarityService
│
▼
Best Matching Category
│
▼
Root Node
│
▼
ConversationState::start()
│
▼
Node Processing
│
├── Question
├── Instruction
├── Action
└── Final
│
▼
JSON Response
The main chatbot services are organized as follows:
app/
├── Http/
│ └── Controllers/
│ └── ChatbotController.php
│
└── Services/
└── bot/
├── BotAuthInfo.php
├── ChatbotService.php
├── ConversationState.php
├── CustomerOverviewService.php
├── DecisionActions.php
├── DecisionTree.php
├── GetCustomerInfoFromOIM.php
└── TextSimilarityService.php
storage/
└── bot/
└── knowledge.json
The project separates different responsibilities into dedicated services.
| Service | Responsibility |
|---|---|
ChatbotController |
HTTP entry point |
ChatbotService |
Conversation orchestration |
DecisionTree |
Category and node selection |
TextSimilarityService |
User message matching |
ConversationState |
Conversation state management |
BotAuthInfo |
Authentication state management |
DecisionActions |
External system operations |
GetCustomerInfoFromOIM |
Customer information and personalization |
CustomerOverviewService |
Customer information aggregation |
This separation follows the Single Responsibility Principle and keeps the controller layer lightweight.
ChatbotService is the main orchestration layer of the chatbot.
It coordinates the other services instead of implementing every responsibility itself.
Its main dependencies are:
DecisionTree
ConversationState
DecisionActions
GetCustomerInfoFromOIM
The main entry point is:
reply(string $message)The method determines whether the user is already inside an active conversation and routes the request accordingly.
DecisionTree is responsible for determining which conversation category best matches the user's message.
It loads the chatbot knowledge base from:
storage/bot/knowledge.json
The main structure is:
categories
│
├── intent_triggers
│
└── tree
│
├── root
│
└── nodes
For example:
{
"id": "internet_problem",
"intent_triggers": [
"internetim yok",
"internete bağlanamıyorum",
"internet çalışmıyor"
]
}
When the user writes:
internte baglantim yok
each trigger is compared against the message using TextSimilarityService.
The category with the highest similarity score is selected if it exceeds the configured threshold.
Current threshold:
0.55
TextSimilarityService provides the text comparison mechanisms used by the chatbot.
The current implementation combines three approaches.
Levenshtein similarity is useful for detecting character-level differences.
It is particularly useful for:
- Typographical errors
- Missing characters
- Extra characters
- Small spelling differences
Example:
User input:
internte baglantim yok
Expected:
internet bağlantım yok
Character-level similarity can help recognize these as related messages.
The current implementation uses PHP's:
similar_text()function to calculate general textual similarity.
Implementation note: The method is currently named
jaroWinkler(), but the implementation actually uses PHP'ssimilar_text()function. This means it is not a true Jaro-Winkler implementation. The method can either be renamed to reflect its current behavior or replaced with an actual Jaro-Winkler algorithm in the future.
Cosine similarity compares the word-frequency representation of two messages.
For example:
internet bağlantım yok
and:
internet bağlantı problemi yaşıyorum
share important terms.
Cosine similarity captures this word-level relationship.
The three similarity methods are combined into a single hybrid score.
Current weights:
Cosine Similarity 55%
Text Similarity 30%
Levenshtein Similarity 15%
Formula:
Hybrid Score =
Cosine × 0.55
+ Text Similarity × 0.30
+ Levenshtein × 0.15
The resulting score is normalized to a range approximately between:
0.0 ───────────────── 1.0
Low similarity High similarity
For example:
Hybrid Score = 0.78
indicates a relatively strong similarity between the two messages.
Before comparing messages, the text is normalized.
For example:
"İNTERNETİM YOK!!!"
can be normalized into:
"internetim yok"
The normalization process includes:
- Lowercase conversion
- Turkish character normalization
- Punctuation removal
- Whitespace normalization
- Trimming
- Tokenization
Example:
"İnternet bağlantım yok!!!"
↓
"internet baglantim yok"
The chatbot uses Laravel sessions to preserve conversation state between requests.
A simplified state can look like:
{
"category_id": "internet_problem",
"node_id": "check_connection",
"temp_value": "12345678",
"customer_name": "Arda"
}
The main state fields are:
| Field | Purpose |
|---|---|
category_id |
Currently active category |
node_id |
Currently active conversation node |
temp_value |
Temporary conversation data |
customer_name |
Customer personalization data |
The project uses the State Design Pattern through the ConversationState class.
The purpose is to centralize conversation state management and allow the chatbot to transition between different conversation states.
A simplified flow:
Node A
│
▼
ConversationState::moveTo()
│
▼
Node B
For example:
Internet Problem
│
▼
Subscriber Number
│
▼
Connection Check
│
▼
Result
Each request can continue from the state established by the previous request.
ConversationState is responsible for maintaining the chatbot's current conversational context.
Its main operations include:
get()
start()
moveTo()
clear()
setTemp()
getTemp()
clearTemp()
setCustomerName()
getCustomerName()
clearCustomerName()The class allows the application to treat the conversation as a sequence of states instead of a collection of unrelated HTTP requests.
BotAuthInfo centrally manages the authentication context used by chatbot services.
Authentication state is stored in the Laravel session under:
chatbot_auth
The service provides:
get()
start()
clear()Other services such as:
DecisionActions
GetCustomerInfoFromOIM
can therefore access the current authentication context without independently managing the authentication state.
Security note: Real usernames, passwords, API keys, and tokens should never be hard-coded into the source code. Production credentials should be stored in environment variables or a dedicated secrets-management system.
GetCustomerInfoFromOIM is responsible for retrieving customer information from the OIM system.
The basic flow is:
BotAuthInfo
│
▼
OIM Login
│
▼
Authentication Token
│
▼
Customer Information
│
▼
Customer Name
│
▼
Personalized Response
For example:
Dear customer Arda,
can be generated dynamically based on the customer's OIM information.
CustomerOverviewService acts as an aggregation layer.
It combines customer information from OIM with operational information retrieved through DecisionActions.
The resulting overview may contain:
- Connection status
- Connection timestamp
- Debt amount
- Payment link
- Subscriber number
- Customer name
- Current tariff
Example:
{
"connection_durum": "online",
"debt": "250.00 ₺",
"payment_linki": "https://example.com/payment",
"connection_zaman": "2026-09-27 14:30:00",
"aboneNumarasi": "12345678",
"isim": "Arda",
"tarife": "100 Mbps"
}
DecisionActions contains the operational integrations between the chatbot and external ISS/OIM services.
The class acts as the integration layer responsible for executing real backend operations.
The main supported operations include:
check_ppp_session()Checks the customer's PPP session status.
Possible states can include:
online
offline
not_found
check_connection_session()Retrieves connection-related information such as:
connection_status
connection_start
connection_end
check_connection_session_for_internet_yok()Provides a dedicated connection lookup for the "I don't have internet" troubleshooting flow.
check_payment_session()Retrieves payment-related information such as:
- Outstanding debt
- Invoice information
- Payment status
- Payment information
check_payment_link_session()Retrieves a payment URL when available.
check_saha_ariza_session()Creates a field-failure ticket through the OIM system.
check_tarife_hiz_session()Retrieves the current plan's upload and download speeds.
For example:
51200k/102400k
can be converted into:
Upload: 50 Mbps
Download: 100 Mbps
check_available_plans_session()Retrieves plans that are currently available to the customer.
check_plan_change_request_session()Submits a plan change request to the OIM system.
One of the more advanced features of the project is dynamic plan selection.
Instead of hard-coding every available internet plan into the conversation tree, the chatbot can retrieve available plans from the external API and dynamically construct conversation branches.
Flow:
User
│
│ "Show available plans"
▼
ChatbotService
│
▼
DecisionActions
│
▼
OIM API
│
▼
Available Plans
│
▼
ConversationState
│
▼
Dynamic Branches
│
▼
User Selection
│
▼
Plan Change Request
For example, an API may return:
[
{
"id": 101,
"name": "100 Mbps",
"download": 100,
"upload": 20
},
{
"id": 102,
"name": "200 Mbps",
"download": 200,
"upload": 40
}
]
The chatbot can then generate the corresponding branches at runtime.
This means that changes to available plans do not necessarily require changes to the chatbot's source code.
Conversation definitions are stored in:
storage/bot/knowledge.json
A simplified structure:
{
"categories": [
{
"id": "internet_problem",
"intent_triggers": [
"internetim yok",
"internete bağlanamıyorum",
"internet çalışmıyor"
],
"tree": {
"root": "node_start",
"nodes": {
"node_start": {
"type": "question",
"text": "How can I help you with your internet connection?",
"branches": []
}
}
}
}
]
}
This separates conversation definitions from PHP application logic.
The conversation tree can contain different node types.
A question node waits for user input.
Example:
Is your modem powered on?
1 - Yes
2 - No
An instruction node does not require user input and can automatically move to another node.
Example:
Your connection is being checked...
An action node executes backend logic.
For example:
check_connection_session
A final node indicates that the current conversation has finished.
The conversation state can then be cleared:
ConversationState::clear()Action results can be mapped to different conversation nodes.
For example:
Action
│
├── online
│ ↓
│ node_online
│
├── offline
│ ↓
│ node_offline
│
└── not_found
↓
node_error
This allows the action implementation and conversation flow to remain relatively independent.
actionTextParser() converts backend action results into user-facing chatbot messages.
For example, the backend might return:
{
"status": "online",
"connection_start": "14:20"
}
The chatbot can transform this into a human-readable response such as:
Your connection appears to be active. Your latest connection started at 14:20.
The parser can work with information such as:
- Customer name
- PPP username
- PPP password
- Connection status
- Connection start/end
- Debt
- Payment link
- Ticket information
- Upload speed
- Download speed
The controller exposes the chatbot through HTTP endpoints.
POST /chatbot
Request:
{
"message": "internetim yok"
}
Example response:
{
"text": "Let's check your internet connection.",
"branches": [
{
"label": "Yes",
"value": "yes"
},
{
"label": "No",
"value": "no"
}
]
}
GET /chatbot/show
Example response:
{
"success": true,
"data": {
"connection_durum": "online",
"debt": "0 ₺",
"payment_linki": null,
"connection_zaman": "2026-09-27 14:30:00",
"aboneNumarasi": "12345678",
"isim": "Arda",
"tarife": "100 Mbps"
}
}
The exact endpoint paths depend on the Laravel routes configured in the project.
A frontend client can send a message using:
fetch('/chatbot', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: 'İnternetim yok'
})
});The backend then processes the request:
ChatbotController
↓
ChatbotService
↓
DecisionTree
↓
TextSimilarityService
↓
Category
↓
ConversationState
merhaba internetim yok
Dear customer Arda, let's check your internet connection.
Is your modem powered on?
evet
I'm checking your connection...
check_connection_session()
{
"connection_status": "offline"
}
Your connection does not appear to be active at the moment.
Chatbot responses generally follow a structure similar to:
{
"text": "Bot response",
"branches": []
}
The branches property represents the options that can be presented to the user.
Example:
{
"text": "Please select an operation.",
"branches": [
{
"label": "Check my connection",
"value": "connection_check"
},
{
"label": "Payment information",
"value": "payment"
}
]
}
Recommended environment:
PHP 8.x
Laravel
Composer
MySQL or compatible database
Redis (optional)
ISS API
OIM API
git clone <repository-url>
cd <project-directory>
composer install
Create the .env file:
cp .env.example .env
Generate the Laravel application key:
php artisan key:generate
Configure your database settings in .env:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=database_user
DB_PASSWORD=database_password
Run migrations:
php artisan migrate
Make sure the chatbot knowledge base exists:
storage/bot/knowledge.json
php artisan serve
External API credentials should be configured through environment variables.
Example:
ISS_API_URL=
OIM_API_URL=
ISS_USERNAME=
ISS_PASSWORD=
OIM_USERNAME=
OIM_PASSWORD=
CUSTOMER_API_KEY=
Laravel configuration files can then expose these values to the application:
config('services.iss.url');Because this chatbot can work with customer information and authentication credentials, security is an important part of the architecture.
The following information should never be committed to the repository:
Username
Password
API Key
API Token
Session Token
Customer Credentials
These values should be stored in:
.env
or a dedicated secret-management system.
A recommended configuration:
.env
.env.*
!.env.example
/storage/*.key
/storage/logs/*
The chatbot may process sensitive customer information such as:
- Subscriber numbers
- Customer names
- Payment information
- PPP credentials
- Connection information
Therefore, sensitive customer data should not unnecessarily appear in:
Application logs
Debug output
Exception logs
API request logs
API response logs
Production logging should be carefully configured to avoid exposing customer data or credentials.
Text similarity calculations can become increasingly expensive as the number of categories and intent triggers grows.
The current matching process is conceptually similar to:
For each category
↓
For each trigger
↓
Normalize text
↓
Calculate Levenshtein
↓
Calculate text similarity
↓
Calculate cosine similarity
↓
Calculate hybrid score
As the knowledge base grows, this can increase CPU usage.
Potential optimizations include:
- Trigger caching
- Normalized trigger caching
- Precomputed vectors
- TF-IDF
- Redis caching
- Embedding-based semantic search
- Dedicated vector databases
Important areas to test include:
internetim yok
İnternetim yok
INTERNETIM YOK
internte yok
internet baglantim yok
These variations should be evaluated against the intended category.
Each intent should be tested with:
- Exact trigger phrases
- Misspelled messages
- Short messages
- Messages containing additional words
- Messages without Turkish characters
- Different capitalization
- Punctuation variations
The following sequence should be tested:
start()
↓
moveTo()
↓
setTemp()
↓
getTemp()
↓
clearTemp()
↓
clear()
External API failure scenarios should also be tested:
200 OK
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
500 Internal Server Error
Timeout
Invalid JSON
Unexpected response
Business logic is not placed directly inside the controller.
Instead:
Controller
↓
Service
↓
External API
This provides:
- Better separation of concerns
- Improved testability
- Cleaner controllers
- Reusable business logic
- Easier maintenance
Conversation flows are not hard-coded entirely into PHP classes.
Instead, they are represented in the knowledge base.
This means:
PHP Code
│
│ remains mostly unchanged
▼
knowledge.json
│
▼
Conversation Flow
can be modified independently.
The State Design Pattern allows the chatbot to preserve context between requests.
For example:
Question
↓
User Input
↓
Next Node
↓
Action
↓
Result
↓
Next Node
The ConversationState service centralizes this state transition process.
Each major component has a specific responsibility:
ChatbotController
↓
HTTP Layer
ChatbotService
↓
Conversation Orchestration
DecisionTree
↓
Decision Making
TextSimilarityService
↓
Text Matching
ConversationState
↓
Conversation State
BotAuthInfo
↓
Authentication State
DecisionActions
↓
External Operations
GetCustomerInfoFromOIM
↓
Customer Information
CustomerOverviewService
↓
Customer Data Aggregation
This separation makes the architecture easier to understand, test, and extend.
A new conversation topic can be added to the knowledge base.
For example:
{
"id": "modem_problem",
"intent_triggers": [
"modemim bozuldu",
"modem çalışmıyor",
"modem arızalı"
],
"tree": {
"root": "modem_start",
"nodes": {
"modem_start": {
"type": "question",
"text": "Are the lights on your modem?",
"branches": []
}
}
}
}
Once added, the new category can be evaluated by DecisionTree.
A new backend operation can be added to DecisionActions.
For example:
public function check_modem_status(string $subscriberId): array
{
// API request
}The corresponding action can then be referenced from the conversation tree.
If a conversation needs to store additional temporary information, ConversationState can be extended with a dedicated getter/setter pair.
For example:
setTicketNumber()
getTicketNumber()
clearTicketNumber()The value can then become part of the active conversation state.
Because the chatbot depends on external services, several failure scenarios must be handled:
Authentication failure
API timeout
Invalid API response
Missing customer
Invalid subscriber number
Invalid JSON
Unexpected API status
Missing action
Missing node
Invalid conversation state
External API failures should generally be converted into meaningful user-facing chatbot responses rather than exposing raw technical exceptions.
The current system uses:
Levenshtein
similar_text()
Cosine Similarity
A future version could introduce embedding-based semantic search.
For example:
"I cannot access the internet"
"I can't connect to the web"
"My connection is completely down"
may be semantically related even when they have relatively different word structures.
A dedicated intent classification layer could be placed before the decision tree:
User Message
↓
Intent Classifier
↓
Category
↓
Decision Tree
↓
Conversation Node
For high-traffic deployments, conversation state could be stored in Redis instead of the default session storage.
User
↓
Laravel
↓
Redis
↓
Conversation State
External API calls could implement controlled retries:
Request
↓
Failure
↓
Retry
↓
Failure
↓
Fallback
This could improve resilience against temporary network or service failures.
Long-running or asynchronous operations could be moved to Laravel queues.
Potential candidates include:
Ticket creation
Notifications
Analytics
Logging
Background synchronization
The system could collect metrics such as:
Most common intents
Failed intent matches
Average conversation length
Most frequently used actions
API error rate
Fallback frequency
Successful resolution rate
These metrics could help identify weaknesses in the conversation tree and improve the chatbot over time.
If the application evolves into a larger production system, the architecture could be extended toward:
┌──────────────┐
│ Client │
└───────┬──────┘
│
▼
┌──────────────┐
│ API Gateway │
└───────┬──────┘
│
▼
┌────────────────┐
│ ChatbotService │
└───────┬────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
Intent Engine State Manager Action Engine
│ │ │
▼ ▼ ▼
Similarity Redis ISS / OIM
Engine
For a request such as:
POST /chatbot
with:
{
"message": "Do I have any outstanding debt?"
}
the system can process the request as follows:
ChatbotController
↓
ChatbotService
↓
ConversationState
↓
DecisionTree
↓
TextSimilarityService
↓
Payment Category
↓
Payment Node
↓
DecisionActions
↓
check_payment_session()
↓
ISS API
↓
Payment Result
↓
actionTextParser()
↓
JSON Response
This project brings together several backend and software-engineering concepts:
Business logic is separated from the HTTP controller.
Laravel's dependency injection system is used to provide services to other components.
Conversation state is managed centrally through ConversationState.
Conversation flow is represented as a deterministic decision structure.
Conversation definitions are stored in a JSON knowledge base.
Multiple text similarity algorithms are combined into a single matching score.
The chatbot communicates with external ISS and OIM services.
Conversation and authentication contexts are persisted between requests.
Conversation branches can be generated dynamically from external API data.
Each service has a clearly defined responsibility.
The complete architecture can be summarized as:
USER
│
▼
ChatbotController
│
▼
ChatbotService
│
┌──────────┴──────────┐
│ │
▼ ▼
DecisionTree ConversationState
│ │
▼ │
TextSimilarityService │
│ │
└──────────┬──────────┘
▼
DecisionActions
│
┌──────┴──────┐
│ │
▼ ▼
ISS API OIM API
│ │
└──────┬──────┘
▼
Final Response
The architecture transforms the chatbot from a simple static response system into a backend application capable of:
- Natural-language-style intent matching
- Multi-step conversation management
- Stateful interactions
- Customer personalization
- Real-time external API operations
- Payment and connection workflows
- Dynamic plan selection
- Data-driven conversation flows
- Extensible service-based architecture
The appropriate license should be selected based on the intended distribution model of the project.
For an open-source release, for example:
MIT License
may be considered.
For proprietary or commercial deployments, a custom license may be more appropriate.
This project combines:
Laravel
+
Service-Oriented Architecture
+
Dependency Injection
+
State Design Pattern
+
Decision Tree
+
Text Similarity
+
REST API Integration
+
Session Management
+
Dynamic Conversation Flow
The result is a modular ISP customer-support chatbot backend capable of combining deterministic conversation logic, similarity-based message matching, stateful conversations, customer personalization, and real-time external system integration.