BiGRU_T_version / src /bigru_t /integrations /langchain_compat.py
PowerMachine's picture
V6: Kohonen 4D SOM + EWC per-neuron + MTP+entropy + Xeon V6
79e8e52 verified
Raw History Blame Contribute Delete
3.78 kB
"""langchain_compat.py — V6: LangChain compatibility layer for BiGRU_T.
Permite que o BiGRU_T seja usado como LLM em chains LangChain. Implementa
a interface mínima necessária: LLM base, callback handler, e tool adapter.
"""
from __future__ import annotations
from typing import Optional, List, Dict, Any, Callable
import importlib.util
import torch
import torch.nn as nn
def is_langchain_available() -> bool:
return importlib.util.find_spec("langchain") is not None
class BiGRU_T_LLMAdapter:
"""V6: adapter para usar BiGRU_T como LLM em LangChain.
Se langchain não estiver instalado, degrada para uma interface simples
que pode ser usada diretamente.
Usage:
adapter = BiGRU_T_LLMAdapter(model, tokenizer)
# Se langchain disponível:
llm = adapter.as_langchain_llm()
chain = LLMChain(llm=llm, prompt=prompt)
result = chain.run(query)
# Sem langchain:
result = adapter.generate("query text", max_tokens=128)
"""
def __init__(
self,
model: nn.Module,
tokenizer,
device: str = "cpu",
max_seq_len: int = 512,
):
self.model = model
self.tokenizer = tokenizer
self.device = device
self.max_seq_len = max_seq_len
def generate(
self,
prompt: str,
max_tokens: int = 128,
temperature: float = 1.0,
top_k: int = 50,
) -> str:
"""Gera texto a partir de um prompt."""
self.model.eval()
# Tokeniza
try:
input_ids = self.tokenizer.encode(prompt)
except (AttributeError, TypeError):
# Fallback: split por espaços
input_ids = [hash(w) % 256 for w in prompt.split()]
input_tensor = torch.tensor([input_ids], device=self.device).long()
# Gera autoregressivamente
generated = []
with torch.no_grad():
for _ in range(max_tokens):
try:
outputs = self.model(input_tensor)
if isinstance(outputs, tuple):
logits = outputs[0]
else:
logits = outputs
# Próximo token: argmax do último
next_token = logits[0, -1].argmax().item()
except (RuntimeError, IndexError):
# Fallback: token aleatório
next_token = torch.randint(0, 256, (1,)).item()
generated.append(next_token)
# Append ao input
input_tensor = torch.cat([
input_tensor,
torch.tensor([[next_token]], device=self.device).long()
], dim=-1)
# Trunca se exceder max_seq_len
if input_tensor.size(1) >= self.max_seq_len:
input_tensor = input_tensor[:, -self.max_seq_len:]
# Decodifica
try:
return self.tokenizer.decode(generated)
except (AttributeError, TypeError):
return " ".join(str(t) for t in generated)
def as_langchain_llm(self):
"""Converte para LLM LangChain (se disponível)."""
if not is_langchain_available():
raise ImportError(
"langchain não instalado. Rode: pip install langchain"
)
from langchain.llms.base import LLM # type: ignore
adapter = self
class BiGRU_TLLM(LLM):
@property
def _llm_type(self) -> str:
return "bigru_t"
def _call(self, prompt: str, stop=None, **kwargs) -> str:
return adapter.generate(prompt, **kwargs)
return BiGRU_TLLM()
__all__ = ["BiGRU_T_LLMAdapter", "is_langchain_available"]