sonika-langchain-bot 0.0.10__tar.gz → 0.0.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sonika_langchain_bot-0.0.11/PKG-INFO +215 -0
- sonika_langchain_bot-0.0.11/README.md +174 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/setup.py +17 -17
- sonika_langchain_bot-0.0.10/src/sonika_langchain_bot/langchain_bot_agent_bdi.py → sonika_langchain_bot-0.0.11/src/sonika_langchain_bot/langchain_bot_agent.py +99 -34
- sonika_langchain_bot-0.0.11/src/sonika_langchain_bot.egg-info/PKG-INFO +215 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot.egg-info/SOURCES.txt +1 -2
- sonika_langchain_bot-0.0.11/src/sonika_langchain_bot.egg-info/requires.txt +19 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/test/test.py +11 -19
- sonika_langchain_bot-0.0.10/PKG-INFO +0 -145
- sonika_langchain_bot-0.0.10/README.md +0 -113
- sonika_langchain_bot-0.0.10/src/sonika_langchain_bot/langchain_bdi.py +0 -176
- sonika_langchain_bot-0.0.10/src/sonika_langchain_bot.egg-info/PKG-INFO +0 -145
- sonika_langchain_bot-0.0.10/src/sonika_langchain_bot.egg-info/requires.txt +0 -20
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/LICENSE +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/setup.cfg +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot/__init__.py +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot/langchain_clasificator.py +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot/langchain_class.py +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot/langchain_files.py +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot/langchain_models.py +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot/langchain_tools.py +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot.egg-info/dependency_links.txt +0 -0
- {sonika_langchain_bot-0.0.10 → sonika_langchain_bot-0.0.11}/src/sonika_langchain_bot.egg-info/top_level.txt +0 -0
@@ -0,0 +1,215 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: sonika-langchain-bot
|
3
|
+
Version: 0.0.11
|
4
|
+
Summary: Agente langchain con LLM
|
5
|
+
Author: Erley Blanco Carvajal
|
6
|
+
License: MIT License
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
9
|
+
Classifier: Operating System :: OS Independent
|
10
|
+
Requires-Python: >=3.6
|
11
|
+
Description-Content-Type: text/markdown
|
12
|
+
License-File: LICENSE
|
13
|
+
Requires-Dist: langchain==0.3.26
|
14
|
+
Requires-Dist: langchain-community==0.3.26
|
15
|
+
Requires-Dist: langchain-core==0.3.66
|
16
|
+
Requires-Dist: langchain-openai==0.3.24
|
17
|
+
Requires-Dist: langgraph==0.4.8
|
18
|
+
Requires-Dist: langgraph-checkpoint==2.1.0
|
19
|
+
Requires-Dist: langgraph-sdk==0.1.70
|
20
|
+
Requires-Dist: dataclasses-json==0.6.7
|
21
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
22
|
+
Requires-Dist: pydantic==2.11.7
|
23
|
+
Requires-Dist: faiss-cpu==1.11.0
|
24
|
+
Requires-Dist: pypdf==5.6.1
|
25
|
+
Requires-Dist: python-dotenv==1.0.1
|
26
|
+
Requires-Dist: typing_extensions==4.14.0
|
27
|
+
Requires-Dist: typing-inspect==0.9.0
|
28
|
+
Provides-Extra: dev
|
29
|
+
Requires-Dist: sphinx<9.0.0,>=8.1.3; extra == "dev"
|
30
|
+
Requires-Dist: sphinx-rtd-theme<4.0.0,>=3.0.1; extra == "dev"
|
31
|
+
Dynamic: author
|
32
|
+
Dynamic: classifier
|
33
|
+
Dynamic: description
|
34
|
+
Dynamic: description-content-type
|
35
|
+
Dynamic: license
|
36
|
+
Dynamic: license-file
|
37
|
+
Dynamic: provides-extra
|
38
|
+
Dynamic: requires-dist
|
39
|
+
Dynamic: requires-python
|
40
|
+
Dynamic: summary
|
41
|
+
|
42
|
+
# Sonika LangChain Bot <a href="https://pepy.tech/projects/sonika-langchain-bot"><img src="https://static.pepy.tech/badge/sonika-langchain-bot" alt="PyPI Downloads"></a>
|
43
|
+
|
44
|
+
A Python library that implements a conversational agent using LangChain with tool execution capabilities and text classification.
|
45
|
+
|
46
|
+
## Installation
|
47
|
+
|
48
|
+
```bash
|
49
|
+
pip install sonika-langchain-bot
|
50
|
+
```
|
51
|
+
|
52
|
+
## Prerequisites
|
53
|
+
|
54
|
+
You'll need the following API keys:
|
55
|
+
|
56
|
+
- OpenAI API Key
|
57
|
+
|
58
|
+
Create a `.env` file in the root of your project with the following variables:
|
59
|
+
|
60
|
+
```env
|
61
|
+
OPENAI_API_KEY=your_api_key_here
|
62
|
+
```
|
63
|
+
|
64
|
+
## Key Features
|
65
|
+
|
66
|
+
- Conversational agent with tool execution capabilities
|
67
|
+
- Text classification with structured output
|
68
|
+
- Custom tool integration
|
69
|
+
- Streaming responses
|
70
|
+
- Conversation history management
|
71
|
+
- Flexible instruction-based behavior
|
72
|
+
|
73
|
+
## Basic Usage
|
74
|
+
|
75
|
+
### Agent with Tools Example
|
76
|
+
|
77
|
+
```python
|
78
|
+
import os
|
79
|
+
from dotenv import load_dotenv
|
80
|
+
from langchain_openai import OpenAIEmbeddings
|
81
|
+
from sonika_langchain_bot.langchain_tools import EmailTool
|
82
|
+
from sonika_langchain_bot.langchain_bot_agent import LangChainBot
|
83
|
+
from sonika_langchain_bot.langchain_class import Message, ResponseModel
|
84
|
+
from sonika_langchain_bot.langchain_models import OpenAILanguageModel
|
85
|
+
|
86
|
+
# Load environment variables
|
87
|
+
load_dotenv()
|
88
|
+
|
89
|
+
# Get API key from .env file
|
90
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
91
|
+
|
92
|
+
# Initialize language model and embeddings
|
93
|
+
language_model = OpenAILanguageModel(api_key, model_name='gpt-4o-mini-2024-07-18', temperature=1)
|
94
|
+
embeddings = OpenAIEmbeddings(api_key=api_key)
|
95
|
+
|
96
|
+
# Configure tools
|
97
|
+
tools = [EmailTool()]
|
98
|
+
|
99
|
+
# Create agent instance
|
100
|
+
bot = LangChainBot(language_model, embeddings, instructions="You are an agent", tools=tools)
|
101
|
+
|
102
|
+
# Load conversation history
|
103
|
+
bot.load_conversation_history([Message(content="My name is Erley", is_bot=False)])
|
104
|
+
|
105
|
+
# Get response
|
106
|
+
user_message = 'Send an email with the tool to erley@gmail.com with subject Hello and message Hello Erley'
|
107
|
+
response_model: ResponseModel = bot.get_response(user_message)
|
108
|
+
|
109
|
+
print(response_model)
|
110
|
+
```
|
111
|
+
|
112
|
+
### Streaming Response Example
|
113
|
+
|
114
|
+
```python
|
115
|
+
import os
|
116
|
+
from dotenv import load_dotenv
|
117
|
+
from langchain_openai import OpenAIEmbeddings
|
118
|
+
from sonika_langchain_bot.langchain_bot_agent import LangChainBot
|
119
|
+
from sonika_langchain_bot.langchain_class import Message
|
120
|
+
from sonika_langchain_bot.langchain_models import OpenAILanguageModel
|
121
|
+
|
122
|
+
# Load environment variables
|
123
|
+
load_dotenv()
|
124
|
+
|
125
|
+
# Get API key from .env file
|
126
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
127
|
+
|
128
|
+
# Initialize language model and embeddings
|
129
|
+
language_model = OpenAILanguageModel(api_key, model_name='gpt-4o-mini-2024-07-18', temperature=1)
|
130
|
+
embeddings = OpenAIEmbeddings(api_key=api_key)
|
131
|
+
|
132
|
+
# Create agent instance
|
133
|
+
bot = LangChainBot(language_model, embeddings, instructions="Only answers in english", tools=[])
|
134
|
+
|
135
|
+
# Load conversation history
|
136
|
+
bot.load_conversation_history([Message(content="My name is Erley", is_bot=False)])
|
137
|
+
|
138
|
+
# Get streaming response
|
139
|
+
user_message = 'Hello, what is my name?'
|
140
|
+
for chunk in bot.get_response_stream(user_message):
|
141
|
+
print(chunk)
|
142
|
+
```
|
143
|
+
|
144
|
+
### Text Classification Example
|
145
|
+
|
146
|
+
```python
|
147
|
+
import os
|
148
|
+
from dotenv import load_dotenv
|
149
|
+
from sonika_langchain_bot.langchain_clasificator import TextClassifier
|
150
|
+
from sonika_langchain_bot.langchain_models import OpenAILanguageModel
|
151
|
+
from pydantic import BaseModel, Field
|
152
|
+
|
153
|
+
# Load environment variables
|
154
|
+
load_dotenv()
|
155
|
+
|
156
|
+
# Define classification structure with Pydantic
|
157
|
+
class Classification(BaseModel):
|
158
|
+
intention: str = Field()
|
159
|
+
sentiment: str = Field(..., enum=["happy", "neutral", "sad", "excited"])
|
160
|
+
aggressiveness: int = Field(
|
161
|
+
...,
|
162
|
+
description="describes how aggressive the statement is, the higher the number the more aggressive",
|
163
|
+
enum=[1, 2, 3, 4, 5],
|
164
|
+
)
|
165
|
+
language: str = Field(
|
166
|
+
..., enum=["spanish", "english", "french", "german", "italian"]
|
167
|
+
)
|
168
|
+
|
169
|
+
# Initialize classifier
|
170
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
171
|
+
model = OpenAILanguageModel(api_key=api_key)
|
172
|
+
classifier = TextClassifier(llm=model, validation_class=Classification)
|
173
|
+
|
174
|
+
# Classify text
|
175
|
+
result = classifier.classify("how are you?")
|
176
|
+
print(result)
|
177
|
+
```
|
178
|
+
|
179
|
+
## Available Classes and Components
|
180
|
+
|
181
|
+
### Core Classes
|
182
|
+
|
183
|
+
- **LangChainBot**: Main conversational agent for task execution with tools
|
184
|
+
- **OpenAILanguageModel**: Wrapper for OpenAI language models
|
185
|
+
- **TextClassifier**: Text classification using structured output
|
186
|
+
- **Message**: Message structure for conversation history
|
187
|
+
- **ResponseModel**: Response structure from agent interactions
|
188
|
+
|
189
|
+
### Tools
|
190
|
+
|
191
|
+
- **EmailTool**: Tool for sending emails through the agent
|
192
|
+
|
193
|
+
## Project Structure
|
194
|
+
|
195
|
+
```
|
196
|
+
your_project/
|
197
|
+
├── .env # Environment variables
|
198
|
+
├── src/
|
199
|
+
│ └── sonika_langchain_bot/
|
200
|
+
│ ├── langchain_bot_agent.py
|
201
|
+
│ ├── langchain_clasificator.py
|
202
|
+
│ ├── langchain_class.py
|
203
|
+
│ ├── langchain_models.py
|
204
|
+
│ └── langchain_tools.py
|
205
|
+
└── tests/
|
206
|
+
└── test_bot.py
|
207
|
+
```
|
208
|
+
|
209
|
+
## Contributing
|
210
|
+
|
211
|
+
Contributions are welcome. Please open an issue to discuss major changes you'd like to make.
|
212
|
+
|
213
|
+
## License
|
214
|
+
|
215
|
+
This project is licensed under the MIT License.
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# Sonika LangChain Bot <a href="https://pepy.tech/projects/sonika-langchain-bot"><img src="https://static.pepy.tech/badge/sonika-langchain-bot" alt="PyPI Downloads"></a>
|
2
|
+
|
3
|
+
A Python library that implements a conversational agent using LangChain with tool execution capabilities and text classification.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
pip install sonika-langchain-bot
|
9
|
+
```
|
10
|
+
|
11
|
+
## Prerequisites
|
12
|
+
|
13
|
+
You'll need the following API keys:
|
14
|
+
|
15
|
+
- OpenAI API Key
|
16
|
+
|
17
|
+
Create a `.env` file in the root of your project with the following variables:
|
18
|
+
|
19
|
+
```env
|
20
|
+
OPENAI_API_KEY=your_api_key_here
|
21
|
+
```
|
22
|
+
|
23
|
+
## Key Features
|
24
|
+
|
25
|
+
- Conversational agent with tool execution capabilities
|
26
|
+
- Text classification with structured output
|
27
|
+
- Custom tool integration
|
28
|
+
- Streaming responses
|
29
|
+
- Conversation history management
|
30
|
+
- Flexible instruction-based behavior
|
31
|
+
|
32
|
+
## Basic Usage
|
33
|
+
|
34
|
+
### Agent with Tools Example
|
35
|
+
|
36
|
+
```python
|
37
|
+
import os
|
38
|
+
from dotenv import load_dotenv
|
39
|
+
from langchain_openai import OpenAIEmbeddings
|
40
|
+
from sonika_langchain_bot.langchain_tools import EmailTool
|
41
|
+
from sonika_langchain_bot.langchain_bot_agent import LangChainBot
|
42
|
+
from sonika_langchain_bot.langchain_class import Message, ResponseModel
|
43
|
+
from sonika_langchain_bot.langchain_models import OpenAILanguageModel
|
44
|
+
|
45
|
+
# Load environment variables
|
46
|
+
load_dotenv()
|
47
|
+
|
48
|
+
# Get API key from .env file
|
49
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
50
|
+
|
51
|
+
# Initialize language model and embeddings
|
52
|
+
language_model = OpenAILanguageModel(api_key, model_name='gpt-4o-mini-2024-07-18', temperature=1)
|
53
|
+
embeddings = OpenAIEmbeddings(api_key=api_key)
|
54
|
+
|
55
|
+
# Configure tools
|
56
|
+
tools = [EmailTool()]
|
57
|
+
|
58
|
+
# Create agent instance
|
59
|
+
bot = LangChainBot(language_model, embeddings, instructions="You are an agent", tools=tools)
|
60
|
+
|
61
|
+
# Load conversation history
|
62
|
+
bot.load_conversation_history([Message(content="My name is Erley", is_bot=False)])
|
63
|
+
|
64
|
+
# Get response
|
65
|
+
user_message = 'Send an email with the tool to erley@gmail.com with subject Hello and message Hello Erley'
|
66
|
+
response_model: ResponseModel = bot.get_response(user_message)
|
67
|
+
|
68
|
+
print(response_model)
|
69
|
+
```
|
70
|
+
|
71
|
+
### Streaming Response Example
|
72
|
+
|
73
|
+
```python
|
74
|
+
import os
|
75
|
+
from dotenv import load_dotenv
|
76
|
+
from langchain_openai import OpenAIEmbeddings
|
77
|
+
from sonika_langchain_bot.langchain_bot_agent import LangChainBot
|
78
|
+
from sonika_langchain_bot.langchain_class import Message
|
79
|
+
from sonika_langchain_bot.langchain_models import OpenAILanguageModel
|
80
|
+
|
81
|
+
# Load environment variables
|
82
|
+
load_dotenv()
|
83
|
+
|
84
|
+
# Get API key from .env file
|
85
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
86
|
+
|
87
|
+
# Initialize language model and embeddings
|
88
|
+
language_model = OpenAILanguageModel(api_key, model_name='gpt-4o-mini-2024-07-18', temperature=1)
|
89
|
+
embeddings = OpenAIEmbeddings(api_key=api_key)
|
90
|
+
|
91
|
+
# Create agent instance
|
92
|
+
bot = LangChainBot(language_model, embeddings, instructions="Only answers in english", tools=[])
|
93
|
+
|
94
|
+
# Load conversation history
|
95
|
+
bot.load_conversation_history([Message(content="My name is Erley", is_bot=False)])
|
96
|
+
|
97
|
+
# Get streaming response
|
98
|
+
user_message = 'Hello, what is my name?'
|
99
|
+
for chunk in bot.get_response_stream(user_message):
|
100
|
+
print(chunk)
|
101
|
+
```
|
102
|
+
|
103
|
+
### Text Classification Example
|
104
|
+
|
105
|
+
```python
|
106
|
+
import os
|
107
|
+
from dotenv import load_dotenv
|
108
|
+
from sonika_langchain_bot.langchain_clasificator import TextClassifier
|
109
|
+
from sonika_langchain_bot.langchain_models import OpenAILanguageModel
|
110
|
+
from pydantic import BaseModel, Field
|
111
|
+
|
112
|
+
# Load environment variables
|
113
|
+
load_dotenv()
|
114
|
+
|
115
|
+
# Define classification structure with Pydantic
|
116
|
+
class Classification(BaseModel):
|
117
|
+
intention: str = Field()
|
118
|
+
sentiment: str = Field(..., enum=["happy", "neutral", "sad", "excited"])
|
119
|
+
aggressiveness: int = Field(
|
120
|
+
...,
|
121
|
+
description="describes how aggressive the statement is, the higher the number the more aggressive",
|
122
|
+
enum=[1, 2, 3, 4, 5],
|
123
|
+
)
|
124
|
+
language: str = Field(
|
125
|
+
..., enum=["spanish", "english", "french", "german", "italian"]
|
126
|
+
)
|
127
|
+
|
128
|
+
# Initialize classifier
|
129
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
130
|
+
model = OpenAILanguageModel(api_key=api_key)
|
131
|
+
classifier = TextClassifier(llm=model, validation_class=Classification)
|
132
|
+
|
133
|
+
# Classify text
|
134
|
+
result = classifier.classify("how are you?")
|
135
|
+
print(result)
|
136
|
+
```
|
137
|
+
|
138
|
+
## Available Classes and Components
|
139
|
+
|
140
|
+
### Core Classes
|
141
|
+
|
142
|
+
- **LangChainBot**: Main conversational agent for task execution with tools
|
143
|
+
- **OpenAILanguageModel**: Wrapper for OpenAI language models
|
144
|
+
- **TextClassifier**: Text classification using structured output
|
145
|
+
- **Message**: Message structure for conversation history
|
146
|
+
- **ResponseModel**: Response structure from agent interactions
|
147
|
+
|
148
|
+
### Tools
|
149
|
+
|
150
|
+
- **EmailTool**: Tool for sending emails through the agent
|
151
|
+
|
152
|
+
## Project Structure
|
153
|
+
|
154
|
+
```
|
155
|
+
your_project/
|
156
|
+
├── .env # Environment variables
|
157
|
+
├── src/
|
158
|
+
│ └── sonika_langchain_bot/
|
159
|
+
│ ├── langchain_bot_agent.py
|
160
|
+
│ ├── langchain_clasificator.py
|
161
|
+
│ ├── langchain_class.py
|
162
|
+
│ ├── langchain_models.py
|
163
|
+
│ └── langchain_tools.py
|
164
|
+
└── tests/
|
165
|
+
└── test_bot.py
|
166
|
+
```
|
167
|
+
|
168
|
+
## Contributing
|
169
|
+
|
170
|
+
Contributions are welcome. Please open an issue to discuss major changes you'd like to make.
|
171
|
+
|
172
|
+
## License
|
173
|
+
|
174
|
+
This project is licensed under the MIT License.
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name="sonika-langchain-bot",
|
5
|
-
version="0.0.
|
5
|
+
version="0.0.11",
|
6
6
|
description="Agente langchain con LLM",
|
7
7
|
author="Erley Blanco Carvajal",
|
8
8
|
license="MIT License",
|
@@ -11,23 +11,23 @@ setup(
|
|
11
11
|
packages=find_packages(where="src"), # Encuentra los paquetes dentro de "src"
|
12
12
|
package_dir={"": "src"}, # Indica que los paquetes están en el directorio "src"
|
13
13
|
install_requires=[
|
14
|
-
"langchain
|
15
|
-
"langchain-community
|
16
|
-
"langchain-core
|
17
|
-
"langchain-openai
|
18
|
-
"langgraph
|
19
|
-
"langgraph-checkpoint
|
20
|
-
"langgraph-sdk
|
21
|
-
"dataclasses-json
|
22
|
-
"python-dateutil
|
23
|
-
"
|
24
|
-
"
|
25
|
-
"
|
26
|
-
"
|
27
|
-
"
|
28
|
-
"
|
29
|
-
"typing-inspect>=0.9.0,<1.0.0",
|
14
|
+
"langchain==0.3.26",
|
15
|
+
"langchain-community==0.3.26",
|
16
|
+
"langchain-core==0.3.66",
|
17
|
+
"langchain-openai==0.3.24",
|
18
|
+
"langgraph==0.4.8",
|
19
|
+
"langgraph-checkpoint==2.1.0",
|
20
|
+
"langgraph-sdk==0.1.70",
|
21
|
+
"dataclasses-json==0.6.7",
|
22
|
+
"python-dateutil==2.9.0.post0",
|
23
|
+
"pydantic==2.11.7",
|
24
|
+
"faiss-cpu==1.11.0",
|
25
|
+
"pypdf==5.6.1",
|
26
|
+
"python-dotenv==1.0.1",
|
27
|
+
"typing_extensions==4.14.0",
|
28
|
+
"typing-inspect==0.9.0",
|
30
29
|
],
|
30
|
+
|
31
31
|
extras_require={
|
32
32
|
"dev": [
|
33
33
|
"sphinx>=8.1.3,<9.0.0",
|
@@ -1,11 +1,8 @@
|
|
1
|
-
from typing import Generator
|
2
|
-
from typing import List
|
3
|
-
from langchain.memory import ConversationBufferMemory
|
1
|
+
from typing import Generator, List
|
4
2
|
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder, SystemMessagePromptTemplate, HumanMessagePromptTemplate
|
5
|
-
from langchain.schema import AIMessage, HumanMessage
|
3
|
+
from langchain.schema import AIMessage, HumanMessage, BaseMessage
|
6
4
|
from langchain.text_splitter import CharacterTextSplitter
|
7
5
|
from langchain_community.vectorstores import FAISS
|
8
|
-
from sonika_langchain_bot.langchain_bdi import Belief, BotBeliefSystem
|
9
6
|
from sonika_langchain_bot.langchain_class import FileProcessorInterface, IEmbeddings, ILanguageModel, Message, ResponseModel
|
10
7
|
from langgraph.checkpoint.memory import MemorySaver
|
11
8
|
from langgraph.prebuilt import create_react_agent
|
@@ -18,35 +15,72 @@ class LangChainBot:
|
|
18
15
|
memoria de conversación y uso de herramientas personalizadas.
|
19
16
|
"""
|
20
17
|
|
21
|
-
def __init__(self, language_model: ILanguageModel, embeddings: IEmbeddings,
|
18
|
+
def __init__(self, language_model: ILanguageModel, embeddings: IEmbeddings, instructions: str, tools: List[BaseTool]):
|
22
19
|
"""
|
23
20
|
Inicializa el bot con el modelo de lenguaje, embeddings y herramientas necesarias.
|
24
21
|
|
25
22
|
Args:
|
26
23
|
language_model (ILanguageModel): Modelo de lenguaje a utilizar
|
27
24
|
embeddings (IEmbeddings): Modelo de embeddings para procesamiento de texto
|
28
|
-
|
25
|
+
instructions (str): Instrucciones del sistema
|
29
26
|
tools (List[BaseTool]): Lista de herramientas disponibles
|
30
27
|
"""
|
31
28
|
self.language_model = language_model
|
32
29
|
self.embeddings = embeddings
|
33
|
-
|
30
|
+
# Reemplazamos ConversationBufferMemory con una lista simple de mensajes
|
31
|
+
self.chat_history: List[BaseMessage] = []
|
34
32
|
self.memory_agent = MemorySaver()
|
35
33
|
self.vector_store = None
|
36
34
|
self.tools = tools
|
37
|
-
self.
|
38
|
-
self.
|
35
|
+
self.instructions = instructions
|
36
|
+
self.add_tools_to_instructions(tools)
|
39
37
|
self.conversation = self._create_conversation_chain()
|
40
38
|
self.agent_executor = self._create_agent_executor()
|
41
39
|
|
40
|
+
def add_tools_to_instructions(self, tools: List[BaseTool]):
|
41
|
+
"""Agrega información de las herramientas a las instrucciones base del sistema."""
|
42
|
+
if len(tools) == 0:
|
43
|
+
return
|
44
|
+
|
45
|
+
# Instrucciones sobre el uso de herramientas
|
46
|
+
tools_instructions = '''\n\nWhen you want to execute a tool, enclose the command with three asterisks and provide all parameters needed.
|
47
|
+
Ensure you gather all relevant information from the conversation to use the parameters.
|
48
|
+
If information is missing, search online.
|
49
|
+
|
50
|
+
This is a list of the tools you can execute:
|
51
|
+
'''
|
52
|
+
|
53
|
+
# Procesar cada herramienta y agregarla a las instrucciones
|
54
|
+
for tool in tools:
|
55
|
+
tool_name = tool.name
|
56
|
+
tool_description = tool.description
|
57
|
+
|
58
|
+
tools_instructions += f"\nTool Name: {tool_name}\n"
|
59
|
+
tools_instructions += f"Description: {tool_description}\n"
|
60
|
+
|
61
|
+
# Intentar obtener información de parámetros
|
62
|
+
run_method = getattr(tool, '_run', None)
|
63
|
+
if run_method:
|
64
|
+
try:
|
65
|
+
import inspect
|
66
|
+
params = inspect.signature(run_method)
|
67
|
+
tools_instructions += f"Parameters: {params}\n"
|
68
|
+
except:
|
69
|
+
tools_instructions += "Parameters: Not available\n"
|
70
|
+
else:
|
71
|
+
tools_instructions += "Parameters: Not available\n"
|
72
|
+
|
73
|
+
tools_instructions += "---\n"
|
74
|
+
|
75
|
+
# Agregar las instrucciones de herramientas a las instrucciones base
|
76
|
+
self.instructions += tools_instructions
|
77
|
+
|
78
|
+
|
42
79
|
def _create_conversation_chain(self):
|
43
80
|
"""
|
44
81
|
Crea la cadena de conversación con el prompt template y la memoria.
|
45
|
-
Ahora incluye el contexto del sistema de creencias.
|
46
82
|
"""
|
47
|
-
|
48
|
-
full_system_prompt = f"{beliefs_context}\n\n"
|
49
|
-
print(full_system_prompt)
|
83
|
+
full_system_prompt = f"{self.instructions}\n\n"
|
50
84
|
|
51
85
|
prompt = ChatPromptTemplate.from_messages([
|
52
86
|
SystemMessagePromptTemplate.from_template(full_system_prompt),
|
@@ -95,14 +129,16 @@ class LangChainBot:
|
|
95
129
|
if context:
|
96
130
|
augmented_input = f"Context from attached files:\n{context}\n\nUser question: {user_input}"
|
97
131
|
|
98
|
-
|
132
|
+
# Usamos el historial de chat directamente
|
133
|
+
bot_response = self.conversation.invoke({
|
134
|
+
"input": augmented_input,
|
135
|
+
"history": self.chat_history
|
136
|
+
})
|
99
137
|
|
100
|
-
|
101
|
-
|
102
|
-
token_usage= bot_response.response_metadata['token_usage']
|
103
|
-
bot_response = bot_response.content
|
138
|
+
token_usage = bot_response.response_metadata.get('token_usage', {})
|
139
|
+
bot_response_content = bot_response.content
|
104
140
|
|
105
|
-
instruction_tool = self._getInstruccionTool(
|
141
|
+
instruction_tool = self._getInstruccionTool(bot_response_content)
|
106
142
|
|
107
143
|
if instruction_tool:
|
108
144
|
messages = [HumanMessage(content=instruction_tool)]
|
@@ -124,14 +160,14 @@ class LangChainBot:
|
|
124
160
|
for message in response['agent']['messages']:
|
125
161
|
agent_response = message.content
|
126
162
|
|
127
|
-
|
163
|
+
bot_response_content = agent_response if agent_response else tool_response
|
128
164
|
|
129
|
-
user_tokens = token_usage
|
130
|
-
bot_tokens = token_usage
|
165
|
+
user_tokens = token_usage.get('prompt_tokens', 0)
|
166
|
+
bot_tokens = token_usage.get('completion_tokens', 0)
|
131
167
|
|
132
|
-
self.save_messages(user_input,
|
168
|
+
self.save_messages(user_input, bot_response_content)
|
133
169
|
|
134
|
-
return ResponseModel(user_tokens=user_tokens, bot_tokens=bot_tokens, response=
|
170
|
+
return ResponseModel(user_tokens=user_tokens, bot_tokens=bot_tokens, response=bot_response_content)
|
135
171
|
|
136
172
|
def get_response_stream(self, user_input: str) -> Generator[str, None, None]:
|
137
173
|
"""
|
@@ -148,10 +184,20 @@ class LangChainBot:
|
|
148
184
|
if context:
|
149
185
|
augmented_input = f"Context from attached files:\n{context}\n\nUser question: {user_input}"
|
150
186
|
|
151
|
-
|
187
|
+
# Usamos el historial de chat directamente
|
188
|
+
result_stream = self.conversation.stream({
|
189
|
+
"input": augmented_input,
|
190
|
+
"history": self.chat_history
|
191
|
+
})
|
192
|
+
|
193
|
+
full_response = ""
|
152
194
|
for response in result_stream:
|
153
|
-
|
154
|
-
|
195
|
+
content = response.content
|
196
|
+
full_response += content
|
197
|
+
yield content
|
198
|
+
|
199
|
+
# Guardamos los mensajes después del streaming
|
200
|
+
self.save_messages(user_input, full_response)
|
155
201
|
|
156
202
|
def _get_context(self, query: str) -> str:
|
157
203
|
"""
|
@@ -172,7 +218,7 @@ class LangChainBot:
|
|
172
218
|
"""
|
173
219
|
Limpia la memoria de conversación y el almacén de vectores.
|
174
220
|
"""
|
175
|
-
self.
|
221
|
+
self.chat_history.clear()
|
176
222
|
self.vector_store = None
|
177
223
|
|
178
224
|
def load_conversation_history(self, messages: List[Message]):
|
@@ -182,22 +228,23 @@ class LangChainBot:
|
|
182
228
|
Args:
|
183
229
|
messages: Lista de objetos Message que representan cada mensaje.
|
184
230
|
"""
|
231
|
+
self.chat_history.clear()
|
185
232
|
for message in messages:
|
186
233
|
if message.is_bot:
|
187
|
-
self.
|
234
|
+
self.chat_history.append(AIMessage(content=message.content))
|
188
235
|
else:
|
189
|
-
self.
|
236
|
+
self.chat_history.append(HumanMessage(content=message.content))
|
190
237
|
|
191
238
|
def save_messages(self, user_message: str, bot_response: str):
|
192
239
|
"""
|
193
|
-
Guarda los mensajes en
|
240
|
+
Guarda los mensajes en el historial de conversación.
|
194
241
|
|
195
242
|
Args:
|
196
243
|
user_message (str): Mensaje del usuario
|
197
244
|
bot_response (str): Respuesta del bot
|
198
245
|
"""
|
199
|
-
self.
|
200
|
-
self.
|
246
|
+
self.chat_history.append(HumanMessage(content=user_message))
|
247
|
+
self.chat_history.append(AIMessage(content=bot_response))
|
201
248
|
|
202
249
|
def process_file(self, file: FileProcessorInterface):
|
203
250
|
"""
|
@@ -214,3 +261,21 @@ class LangChainBot:
|
|
214
261
|
self.vector_store = FAISS.from_texts([doc.page_content for doc in texts], self.embeddings)
|
215
262
|
else:
|
216
263
|
self.vector_store.add_texts([doc.page_content for doc in texts])
|
264
|
+
|
265
|
+
def get_chat_history(self) -> List[BaseMessage]:
|
266
|
+
"""
|
267
|
+
Obtiene el historial completo de la conversación.
|
268
|
+
|
269
|
+
Returns:
|
270
|
+
List[BaseMessage]: Lista de mensajes de la conversación
|
271
|
+
"""
|
272
|
+
return self.chat_history.copy()
|
273
|
+
|
274
|
+
def set_chat_history(self, history: List[BaseMessage]):
|
275
|
+
"""
|
276
|
+
Establece el historial de conversación.
|
277
|
+
|
278
|
+
Args:
|
279
|
+
history (List[BaseMessage]): Lista de mensajes a establecer
|
280
|
+
"""
|
281
|
+
self.chat_history = history.copy()
|