phichat 0.1.0__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.
- phichat-0.1.0/.github/workflows/publish.yml +34 -0
- phichat-0.1.0/.gitignore +64 -0
- phichat-0.1.0/INTEGRATION_GUIDE.md +341 -0
- phichat-0.1.0/PKG-INFO +313 -0
- phichat-0.1.0/PhiChat/__init__.py +20 -0
- phichat-0.1.0/PhiChat/constants/__init__.py +3 -0
- phichat-0.1.0/PhiChat/constants/constants.py +13 -0
- phichat-0.1.0/PhiChat/model.py +394 -0
- phichat-0.1.0/PhiChat/parsers.py +75 -0
- phichat-0.1.0/PhiChat/tools.py +251 -0
- phichat-0.1.0/README.md +300 -0
- phichat-0.1.0/pyproject.toml +27 -0
- phichat-0.1.0/skills/SKILL.md +98 -0
- phichat-0.1.0/test/test_basic_llm.py +21 -0
- phichat-0.1.0/test/test_mcp_mock.py +28 -0
- phichat-0.1.0/test/test_parsers.py +51 -0
- phichat-0.1.0/test/test_robustness.py +72 -0
- phichat-0.1.0/test/test_streaming_llm.py +36 -0
- phichat-0.1.0/test/test_structured.py +48 -0
- phichat-0.1.0/test/test_tools_llm.py +35 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*" # Se activa al subir tags como v0.1.0
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-publish:
|
|
10
|
+
name: Build and publish PhiChat to PyPI
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment: pypi
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write # Requerido para Trusted Publishing (OIDC)
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.11"
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
run: |
|
|
27
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
28
|
+
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
29
|
+
|
|
30
|
+
- name: Build package
|
|
31
|
+
run: uv build
|
|
32
|
+
|
|
33
|
+
- name: Publish package
|
|
34
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
phichat-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.lib/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
share/python-wheels/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
.installed.cfg
|
|
22
|
+
*.egg
|
|
23
|
+
MANIFEST
|
|
24
|
+
|
|
25
|
+
# Virtual Environments
|
|
26
|
+
.venv/
|
|
27
|
+
venv/
|
|
28
|
+
ENV/
|
|
29
|
+
env/
|
|
30
|
+
bin/
|
|
31
|
+
include/
|
|
32
|
+
lib/
|
|
33
|
+
share/
|
|
34
|
+
pyvenv.cfg
|
|
35
|
+
|
|
36
|
+
# Testing & Linting
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.tox/
|
|
39
|
+
.nox/
|
|
40
|
+
.coverage
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
*.cover
|
|
45
|
+
.hypothesis/
|
|
46
|
+
.ruff_cache/
|
|
47
|
+
.mypy_cache/
|
|
48
|
+
|
|
49
|
+
# IDEs
|
|
50
|
+
.vscode/
|
|
51
|
+
.idea/
|
|
52
|
+
*.swp
|
|
53
|
+
*.swo
|
|
54
|
+
|
|
55
|
+
# Environment variables
|
|
56
|
+
.env
|
|
57
|
+
.env.local
|
|
58
|
+
.env.*.local
|
|
59
|
+
|
|
60
|
+
# OS
|
|
61
|
+
.DS_Store
|
|
62
|
+
Thumbs.db
|
|
63
|
+
laboratory/
|
|
64
|
+
uv.lock
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# ChatPhi: Integración con flujos LangChain
|
|
2
|
+
|
|
3
|
+
ChatPhi hereda de `BaseChatModel` y es compatible con cualquier componente del ecosistema
|
|
4
|
+
LangChain. Este documento describe cómo integrarlo en los patrones más comunes, optimizado para **Phi-4**.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Estructura del paquete
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
PhiChat/
|
|
12
|
+
├── __init__.py # Exporta ChatPhi, create_tool, run_tool_loop y helpers
|
|
13
|
+
├── model.py # Clase ChatPhi (ChatOllama + fixes phi4)
|
|
14
|
+
├── parsers.py # parse_phi4_tool_calls, inject_tool_system_message
|
|
15
|
+
├── tools.py # create_tool, run_tool_loop, arun_tool_loop
|
|
16
|
+
└── constants/
|
|
17
|
+
├── __init__.py # Exporta las constantes del subpaquete
|
|
18
|
+
└── constants.py # _PHI4_TOOL_SYSTEM_SUFFIX, _TOOL_CALL_PATTERNS
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
| Problema en Phi-4 | Solución en ChatPhi |
|
|
24
|
+
| --------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
25
|
+
| Ollama da Error 400 al usar `tools` nativo | `bind_tools` realiza un bypass e inyecta los schemas manualmente en el prompt |
|
|
26
|
+
| El modelo olvida sus propias llamadas pasadas | `_patch_messages` re-inyecta bloques `<|tool_call|>` en el historial |
|
|
27
|
+
| Las respuestas de herramientas son ignoradas | Se encapsulan en etiquetas `<|tool_response|>` nativas |
|
|
28
|
+
| Los tokens de control ensucian el stream | El filtro de streaming robusto bloquea prefijos fragmentados (ej. `<|tool`) |
|
|
29
|
+
| `with_structured_output` impreciso | Override personalizado que usa `format="json"` de Ollama con inyección de esquema |
|
|
30
|
+
|
|
31
|
+
> **Punto Crítico**: La descripción de la tool es lo único que Phi-4 lee para decidir si usarla. Debe ser clara, en lenguaje natural, y mencionar **cuándo** usarla, no solo qué hace.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Importación
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
# Importación directa del paquete (recomendado)
|
|
39
|
+
from PhiChat import ChatPhi, create_tool, run_tool_loop
|
|
40
|
+
|
|
41
|
+
# O por módulo específico
|
|
42
|
+
from PhiChat.model import ChatPhi
|
|
43
|
+
from PhiChat.tools import create_tool, run_tool_loop
|
|
44
|
+
from PhiChat.parsers import parse_phi4_tool_calls
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 1. Pipe básico (LCEL)
|
|
50
|
+
|
|
51
|
+
El patrón más simple. `ChatPhi` se usa como cualquier `ChatModel` en una chain.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from langchain_core.output_parsers import StrOutputParser
|
|
55
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
56
|
+
from PhiChat import ChatPhi
|
|
57
|
+
|
|
58
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
59
|
+
("system", "Eres un experto en {tema}."),
|
|
60
|
+
("human", "{pregunta}"),
|
|
61
|
+
])
|
|
62
|
+
|
|
63
|
+
chain = prompt | ChatPhi() | StrOutputParser()
|
|
64
|
+
|
|
65
|
+
result = chain.invoke({
|
|
66
|
+
"tema": "física cuántica",
|
|
67
|
+
"pregunta": "Explica el entrelazamiento cuántico en 2 líneas.",
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 2. Tool calling con bind_tools
|
|
74
|
+
|
|
75
|
+
### Definir tools con @tool
|
|
76
|
+
|
|
77
|
+
La descripción de cada tool es crítica. Phi-4 decide si usarla basándose exclusivamente en ese texto.
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from langchain_core.tools import tool
|
|
81
|
+
from langchain_core.messages import HumanMessage
|
|
82
|
+
from PhiChat import ChatPhi
|
|
83
|
+
|
|
84
|
+
@tool
|
|
85
|
+
def convertir_moneda(monto: float, de: str, a: str) -> str:
|
|
86
|
+
"""
|
|
87
|
+
Convierte un monto entre divisas.
|
|
88
|
+
Úsala cuando el usuario pregunte sobre conversiones de moneda o tipos de cambio.
|
|
89
|
+
"""
|
|
90
|
+
tasas = {"USD": 1.0, "MXN": 17.2, "EUR": 0.92}
|
|
91
|
+
resultado = monto * (tasas[a] / tasas[de])
|
|
92
|
+
return f"{monto} {de} = {resultado:.2f} {a}"
|
|
93
|
+
|
|
94
|
+
llm = ChatPhi(temperature=0.3)
|
|
95
|
+
chain = llm.bind_tools([convertir_moneda])
|
|
96
|
+
|
|
97
|
+
result = chain.invoke([HumanMessage(content="¿Cuánto es 500 MXN en EUR?")])
|
|
98
|
+
# result.tool_calls -> [{"name": "convertir_moneda", "args": {...}, "id": "..."}]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Definir tools con args_schema (Recomendado)
|
|
102
|
+
|
|
103
|
+
Phi-4 genera argumentos más precisos cuando el esquema tiene `Field(description=...)` explícito en cada campo.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from pydantic import BaseModel, Field
|
|
107
|
+
from PhiChat import ChatPhi, create_tool
|
|
108
|
+
|
|
109
|
+
class BusquedaInput(BaseModel):
|
|
110
|
+
query: str = Field(description="Término a buscar en la base de datos")
|
|
111
|
+
limite: int = Field(default=5, description="Número máximo de resultados a retornar")
|
|
112
|
+
|
|
113
|
+
def buscar_productos(query: str, limite: int = 5) -> str:
|
|
114
|
+
return f"Resultados para '{query}' (max {limite})"
|
|
115
|
+
|
|
116
|
+
tool_busqueda = create_tool(
|
|
117
|
+
func=buscar_productos,
|
|
118
|
+
description=(
|
|
119
|
+
"Busca productos en el catálogo por nombre o categoría. "
|
|
120
|
+
"Úsala cuando el usuario pregunte por disponibilidad o precios."
|
|
121
|
+
),
|
|
122
|
+
args_schema=BusquedaInput,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
chain = ChatPhi().bind_tools([tool_busqueda])
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 3. Mejores Prácticas de Ingeniería (Verificadas)
|
|
131
|
+
|
|
132
|
+
Para garantizar una librería de calidad profesional, sigue estos patrones validados en LangChain v0.3:
|
|
133
|
+
|
|
134
|
+
### A. Manejo de Errores y Auto-Corrección
|
|
135
|
+
No permitas que las herramientas lancen excepciones que rompan el flujo. Captura el error y devuélvelo como un mensaje para que Phi-4 pueda razonar y corregir su llamada.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
@tool
|
|
139
|
+
def mi_herramienta_robusta(param: int) -> str:
|
|
140
|
+
"""Ejecuta una acción sensible."""
|
|
141
|
+
try:
|
|
142
|
+
# Lógica de la herramienta
|
|
143
|
+
return "Éxito"
|
|
144
|
+
except Exception as e:
|
|
145
|
+
# Devolver el error al modelo para que intente otra estrategia
|
|
146
|
+
return f"Error en la herramienta: {str(e)}. Intenta con un valor diferente."
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### B. Validación de Esquemas con Pydantic
|
|
150
|
+
Usa validadores de Pydantic para capturar errores de tipo antes de que lleguen a la lógica de negocio.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from pydantic import BaseModel, Field, field_validator
|
|
154
|
+
|
|
155
|
+
class CalculoInput(BaseModel):
|
|
156
|
+
valor: int = Field(description="Un número positivo")
|
|
157
|
+
|
|
158
|
+
@field_validator("valor")
|
|
159
|
+
@classmethod
|
|
160
|
+
def mayor_que_cero(cls, v: int) -> int:
|
|
161
|
+
if v <= 0:
|
|
162
|
+
raise ValueError("El valor debe ser mayor que cero")
|
|
163
|
+
return v
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### C. Idempotencia y Transacciones Atómicas
|
|
167
|
+
Diseña herramientas que realicen operaciones atómicas. Si un agente reintenta una llamada debido a un timeout, la herramienta debe ser capaz de manejarlo sin duplicar efectos secundarios.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 4. Orquestación con LangGraph: Conceptos Avanzados
|
|
172
|
+
|
|
173
|
+
### A. Super-steps y Tolerancia a Fallos
|
|
174
|
+
LangGraph organiza la ejecución en "super-steps" (ticks del grafo).
|
|
175
|
+
- **Checkpoints**: Se guarda un `StateSnapshot` al final de cada super-step.
|
|
176
|
+
- **Task-level Writes**: Si un nodo falla dentro de un super-step paralelo, LangGraph guarda los resultados de los nodos que sí terminaron. Al reanudar, **solo se re-ejecutan los nodos fallidos**, optimizando el uso de tokens y tiempo.
|
|
177
|
+
|
|
178
|
+
### B. Estructura de un StateSnapshot
|
|
179
|
+
Cuando llamas a `agent.get_state(config)`, obtienes un objeto con:
|
|
180
|
+
- `values`: Valores actuales del estado (mensajes, variables).
|
|
181
|
+
- `next`: Tupla con los nombres de los nodos que se ejecutarán a continuación (vacía si el grafo terminó).
|
|
182
|
+
- `metadata`: Incluye el `source` (input, loop, update) y el `step` (contador de super-steps).
|
|
183
|
+
- `parent_config`: Referencia al checkpoint anterior, permitiendo navegar hacia atrás.
|
|
184
|
+
|
|
185
|
+
### C. Time Travel y Replay
|
|
186
|
+
Puedes re-ejecutar el grafo desde cualquier punto pasado utilizando un `checkpoint_id`:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
# Buscar un checkpoint específico en el historial
|
|
190
|
+
history = list(agent.get_state_history(config))
|
|
191
|
+
old_checkpoint = history[5] # Por ejemplo, 5 pasos atrás
|
|
192
|
+
|
|
193
|
+
# Reanudar desde ese punto
|
|
194
|
+
agent.invoke(None, old_checkpoint.config)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 5. Mejores Prácticas para la Interfaz de Usuario (UI)
|
|
200
|
+
Si estás construyendo un chat basado en `PhiChat`, sigue estas guías para renderizar herramientas:
|
|
201
|
+
|
|
202
|
+
1. **Estados del Ciclo de Vida**: Maneja siempre los tres estados: `pending` (ejecutando), `completed` (éxito) y `error` (fallo).
|
|
203
|
+
2. **Streaming Reactivo**: Usa el `tool_call_chunks` emitido por `ChatPhi` para mostrar un "Loading Card" instantáneo antes de que la herramienta termine de ejecutarse.
|
|
204
|
+
3. **Parseo Seguro**: Los resultados de las herramientas llegan como strings. Usa bloques `try/except` al parsear JSON en el frontend y ofrece una vista genérica (ej. JSON colapsable) si no tienes un componente visual específico para esa herramienta.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 6. Salida estructurada
|
|
209
|
+
|
|
210
|
+
Override del método base. Usa `format="json"` de Ollama internamente e inyecta el esquema en el system prompt de forma automática.
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from pydantic import BaseModel, Field
|
|
214
|
+
from langchain_core.messages import HumanMessage
|
|
215
|
+
from PhiChat import ChatPhi
|
|
216
|
+
|
|
217
|
+
class Resumen(BaseModel):
|
|
218
|
+
titulo: str = Field(description="Título del texto en max. 5 palabras")
|
|
219
|
+
ideas_clave: list[str] = Field(description="Lista de 3 ideas principales")
|
|
220
|
+
sentimiento: str = Field(description="Positivo, Negativo o Neutro")
|
|
221
|
+
puntaje: float = Field(description="Puntaje de 0.0 a 10.0")
|
|
222
|
+
|
|
223
|
+
llm = ChatPhi().with_structured_output(Resumen)
|
|
224
|
+
|
|
225
|
+
result = llm.invoke([HumanMessage(content="Analiza este texto: ...")])
|
|
226
|
+
# result -> Resumen(titulo="...", ideas_clave=[...], ...)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## 4. Loop agéntico sin AgentExecutor
|
|
232
|
+
|
|
233
|
+
Útil para ejecutar múltiples llamadas a herramientas de forma secuencial sin la sobrecarga de un motor de agentes completo.
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
from langchain_core.messages import SystemMessage, HumanMessage
|
|
237
|
+
from langchain_core.tools import tool
|
|
238
|
+
from PhiChat import ChatPhi
|
|
239
|
+
|
|
240
|
+
@tool
|
|
241
|
+
def buscar_producto(nombre: str) -> str:
|
|
242
|
+
"""Busca productos en el catálogo."""
|
|
243
|
+
return f"Detalles de {nombre}..."
|
|
244
|
+
|
|
245
|
+
llm = ChatPhi(temperature=0.2)
|
|
246
|
+
messages = [HumanMessage(content="¿Tienen laptop?")]
|
|
247
|
+
|
|
248
|
+
# Loop: LLM -> tool_call -> resultado -> LLM -> respuesta final
|
|
249
|
+
result = llm.run_tool_loop(
|
|
250
|
+
messages=messages,
|
|
251
|
+
tools=[buscar_producto],
|
|
252
|
+
verbose=True
|
|
253
|
+
)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
> **Nota**: Para aplicaciones asíncronas (web/servidores), utiliza `await llm.arun_tool_loop(...)`.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 5. Streaming
|
|
261
|
+
|
|
262
|
+
El streaming filtra automáticamente los tokens de control y emite chunks limpios.
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
llm = ChatPhi()
|
|
266
|
+
|
|
267
|
+
for chunk in llm.stream("Explica la relatividad"):
|
|
268
|
+
print(chunk.content, end="", flush=True)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## 6. Integración con LangGraph (Recomendado)
|
|
274
|
+
|
|
275
|
+
PhiChat es totalmente compatible con `create_react_agent` y persistencia de estado.
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
from langgraph.prebuilt import create_react_agent
|
|
279
|
+
from langgraph.checkpoint.memory import MemorySaver
|
|
280
|
+
from PhiChat import ChatPhi
|
|
281
|
+
|
|
282
|
+
llm = ChatPhi(temperature=0)
|
|
283
|
+
memory = MemorySaver()
|
|
284
|
+
agent = create_react_agent(llm, tools=[mi_tool], checkpointer=memory)
|
|
285
|
+
|
|
286
|
+
config = {"configurable": {"thread_id": "1"}}
|
|
287
|
+
result = agent.invoke({"messages": [("user", "Hola")]}, config)
|
|
288
|
+
|
|
289
|
+
# Inspección y Manipulación del Estado
|
|
290
|
+
# Recupera el estado actual de la conversación
|
|
291
|
+
state = agent.get_state(config)
|
|
292
|
+
print(state.values["messages"])
|
|
293
|
+
|
|
294
|
+
# Actualizar el estado manualmente (inyectar información)
|
|
295
|
+
agent.update_state(config, {"messages": [HumanMessage(content="Nota: El sistema está en mantenimiento")]})
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Human-in-the-Loop (Interrupción y Aprobación)
|
|
299
|
+
Puedes interrumpir el grafo antes de ejecutar herramientas críticas para validación humana.
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
agent = create_react_agent(
|
|
303
|
+
llm,
|
|
304
|
+
tools=[herramientas_sensibles],
|
|
305
|
+
checkpointer=memory,
|
|
306
|
+
interrupt_before=["tools"] # Se detiene justo antes de llamar a la herramienta
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## 7. Integración con Model Context Protocol (MCP)
|
|
313
|
+
|
|
314
|
+
PhiChat soporta herramientas remotas de servidores MCP de forma nativa.
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
from PhiChat import ChatPhi
|
|
318
|
+
from langchain_mcp_adapters.client import MultiServerMCPClient
|
|
319
|
+
|
|
320
|
+
async def run_mcp():
|
|
321
|
+
async with MultiServerMCPClient({"db": {"transport": "stdio", "command": "python", "args": ["server.py"]}}) as client:
|
|
322
|
+
tools = await client.get_tools()
|
|
323
|
+
llm = ChatPhi()
|
|
324
|
+
# El loop agéntico maneja la ejecución asíncrona de MCP automáticamente
|
|
325
|
+
res = await llm.arun_tool_loop(messages=[...], tools=tools)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Configuración del modelo
|
|
331
|
+
|
|
332
|
+
| Parámetro | Default | Descripción |
|
|
333
|
+
|-----------|---------|-------------|
|
|
334
|
+
| `model` | `phi4` | Modelo Ollama a usar |
|
|
335
|
+
| `temperature` | `0.7` | Creatividad (0.0 para herramientas) |
|
|
336
|
+
| `num_ctx` | `8192` | Ventana de contexto |
|
|
337
|
+
| `keep_alive` | `0` | Tiempo de retención en RAM |
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
llm = ChatPhi(model="phi4:latest", temperature=0, num_ctx=16384)
|
|
341
|
+
```
|