tketool.llm
OpenAI-compatible model access, structured-output prompts, embeddings, and memory.
pip install tketool.llm
Chat Completions
import os
from tketool.llm import OpenAIChatModel
llm = OpenAIChatModel(
model_name="gpt-4o-mini",
apitoken=os.environ["OPENAI_API_KEY"],
base_url="https://api.openai.com/v1",
call_dict={"temperature": 0.2},
)
text = llm("用三句话解释向量检索", return_detail=False)
print(text)
Responses API
import os
from tketool.llm import OpenAIResponsesModel
llm = OpenAIResponsesModel(
model_name="gpt-5-mini",
apitoken=os.environ["OPENAI_API_KEY"],
base_url="https://api.openai.com/v1",
call_dict={"max_output_tokens": 300},
)
text, detail = llm("给出一个最小 RAG 流程", return_detail=True)
print(text)
print(detail)
Both transports accept a complete messages list and return the same detail
shape. OpenAI-compatible gateways are supported by changing base_url and
model_name.
messages = [
{"role": "system", "content": "回答要简洁。"},
{"role": "user", "content": "什么是结构化输出?"},
]
answer = llm("", return_detail=False, messages=messages)
Typed prompt input
PromptInvoker keeps the existing keyword-input API and also accepts a
Pydantic model through invoke(model=None). In a prompt template, {.field}
is a safe shorthand for a declared top-level model field:
from datetime import datetime
from pydantic import BaseModel
from tketool.llm import PromptInvokerPool
class GreetingInput(BaseModel):
name: str
time: datetime
pool = PromptInvokerPool(llm, lang="english", folder="prompts")
result = pool.invoke(
"greeting",
model=GreetingInput(name="Ada", time=datetime.now()),
)
print(result.result)
The greeting template can contain Hello {.name}; time {.time:%H:%M}.
Internally, only model_dump(mode="python") values are passed to the template;
the Python model object is not exposed for attribute traversal. Existing calls
such as pool.get_invoker("greeting")(name="Ada", time="09:30") continue to
work. If both forms provide the same field, the explicit keyword value wins.
The only public package path is tketool.llm; the retired tketool.lmc
namespace and LMC-prefixed type aliases are not shipped.
Local Hugging Face embeddings are optional:
pip install "tketool.llm[local-embeddings]"
Memory
Memory is a small API backed by tketool.storage. Bind one instance to one user,
agent, or project space, then use remember and recall:
from tketool.llm.memory import create_memory
from tketool.storage import MemoryBackend
storage = MemoryBackend()
memory = create_memory(storage=storage, space="users/user-001")
saved = memory.remember(
"用户喜欢喝乌龙茶",
kind="preference",
tags=["profile", "drink"],
metadata={"source": "chat"},
idempotency_key="conversation-42/preference-1",
)
for item in memory.recall("用户喜欢喝什么?", limit=3):
print(item.content, item.score)
memory.update(saved.id, tags=["profile", "confirmed"], if_revision=saved.revision)
memory.forget(saved.id) # soft delete; pass hard=True for physical deletion
storage.close()
Choose persistence when constructing the storage backend; the memory API does not change:
import os
from tketool.storage import SQLiteBackend, create_backend
sqlite_storage = SQLiteBackend("memory.db")
postgres_storage = create_backend(os.environ["DATABASE_URL"])
# DATABASE_URL=postgresql+psycopg://user:password@localhost/app
Install the PostgreSQL driver with pip install "tketool.storage[postgresql]".
MemoryBackend is process-local, SQLite is file-backed, and PostgreSQL uses
the tketool.storage SQLAlchemy adapter.
Lexical retrieval is available by default. Semantic and entity channels are loaded only when their small protocols are injected:
memory = create_memory(
storage=storage,
space="users/user-001",
embedder=my_embedder, # implements embed(text) -> list[float]
entity_extractor=my_entity_extractor, # implements extract(text) -> Iterable[str]
)
semantic = memory.recall("饮品偏好", using=["semantic"])
hybrid = memory.recall("Alice 的偏好", using=["lexical", "semantic", "entity"])
memory.reindex(using=["semantic"]) # after changing the embedding model/version
The built-in OpenAI-compatible embedding provider and tokenizer implement those protocols directly:
import os
from tketool.llm import OpenAIEmbeddingProvider
from tketool.llm.memory import SimpleTokenizer, create_memory
from tketool.storage import MemoryBackend
storage = MemoryBackend()
memory = create_memory(
storage=storage,
tokenizer=SimpleTokenizer(),
embedder=OpenAIEmbeddingProvider(
model_name="text-embedding-3-small",
apitoken=os.environ["OPENAI_API_KEY"],
base_url="https://api.openai.com/v1",
),
)
memory.remember("用户喜欢喝乌龙茶")
print(memory.recall("饮品偏好", using=["semantic"]))
For an offline local model, use LocalTransformerEmbeddingProvider with
local_files_only=True. It resolves a cached Hugging Face snapshot without a
network probe. Entity extraction remains application-specific: inject any
object implementing extract(text) -> Iterable[str].
See tketool.llm.memory.examples for runnable memory, SQLite, and PostgreSQL
examples. The legacy agent/context implementation was removed because it
depended on the retired scheduler. Agent runtime code now lives under
tools/agent_framework and is not part of the tketool.llm distribution.
External agent control
from tketool.llm.agent_proxy import create_agent_proxy, SSHConnection controls
Codex app-server or Hermes ACP with async sessions, streamed tool/text events,
interactions and cancellation. Local and SSH connections use the same API;
remote tools operate on remote files. Hermes client schema support is optional:
pip install "tketool.llm[hermes]". Agents must already be installed and authenticated.
This is a control client, separate from the retired scheduler-based agent runtime. It does not replay failed agent tasks or guarantee execution survives disconnection. See agent proxy architecture and examples.
Metadata
Release files for tketool.llm 2.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tketool_llm-2.0.1.tar.gz | 78.6 kB | Without provenance | Details for tketool_llm-2.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tketool_llm-2.0.1-py3-none-any.whl | Python 3 | none | any | Details for tketool_llm-2.0.1-py3-none-any.whl |
Total release size: 186.7 kB
Release files / tketool_llm-2.0.1.tar.gz
| Download URL | tketool_llm-2.0.1.tar.gz |
|---|---|
| Size | 78.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5eac56f82b9e1a23c5532a9c8d8ed714bb075bf38f7d4b84f7f593d1cbf9a764
|
|
BLAKE2b-256 checksum How to use checksums |
86838f4a70a020d0c6c2ed01586e1882ae1765964892f469aa39cac4b6ee6af5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / tketool_llm-2.0.1-py3-none-any.whl
| Download URL | tketool_llm-2.0.1-py3-none-any.whl |
|---|---|
| Size | 108.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
70fe10a90d32f4e0684d096fcda7b8c754947e660c4b937ef4cb41a27f1bc8f6
|
|
BLAKE2b-256 checksum How to use checksums |
730afd4ab97b203f826464ab41d4eafc25a42dd59653bda0ac1cdd88a0cb29ee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Security for tketool.llm 2.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.