Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ dist/
.env
.samples
.session
.rsazure
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@
All notable changes to this project will be documented in this file.
___

## [0.6.2] - 2025-04-07

### Changed
- Refactored all template files in `samples/templates/` to align with the modular CLI architecture introduced in v0.6.0
- Replaced all uses of `call_azure_openai_handler()` with `main()` function
- Replaced manual print formatting with `ChatResult().print()` for consistent output
- Replaced direct logging calls with `get_logger()` and `result.to_log_dict()`
- Replaced hardcoded message structures with `get_context_messages()` for context support
- Added defensive `response.choices` check and fallback token estimation
- Standardized import style: `import rsazure_openai_toolkit as rschat`
- Wrapped logic in `main()` blocks for reuse and testability

### Affected Templates
- `basic_usage.py.j2`
- `chat_loop_usage.py.j2`
- `env_usage.py.j2`
- `env_chat_loop_usage.py.j2`

> These templates are now fully aligned with the official CLI (`rschat`) and offer consistent logging, context persistence, and safety across all use cases.

### Notes
- No breaking changes
- Recommended: regenerate examples using `rschat-tools samples`
- Version bumped to 0.6.2
___

## [0.6.1] - 2025-04-05

### Changed
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@ A fast, modular, secure, and auditable Python toolkit to integrate with Azure Op

___

## 🚀 What's New in v0.6.0
+ ## 🚀 What's New in v0.6.x

- Object-oriented CLI (`rschat`, `rschat-tools`) — easier to test, extend and reuse
- Persistent session context — with system prompt validation and full/trimmed history tracking
- Reproducible model config — centralized via `get_model_config()` and `ModelConfig`
- Transparent logging — structured logs via `InteractionLogger` (CSV/JSONL)
- Modular architecture — folders like `core/`, `session/`, `logging/`, `model_config/`, etc.

### v0.6.2
- All sample templates have been fully aligned with the core architecture and CLI
- Logging, context, result formatting, and safety checks now follow production-grade standards

> Check the full [CHANGELOG](https://github.com/renan-siqueira/rsazure-openai-toolkit/blob/main/CHANGELOG.md) for details.
___

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "rsazure-openai-toolkit"
version = "0.6.1"
version = "0.6.2"
description = "A fast, modular, secure, and auditable toolkit to integrate with Azure OpenAI — with a friendly CLI and dev-first architecture."
authors = [{ name = "Renan Siqueira Antonio", email = "[email protected]" }]
readme = { file = "README.md", content-type = "text/markdown" }
Expand Down
2 changes: 1 addition & 1 deletion src/rsazure_openai_toolkit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
- rschat.ContextInfo(...)
"""

__version__ = "0.6.1"
__version__ = "0.6.2"
__description__ = "A fast, modular, secure, and auditable toolkit to integrate with Azure OpenAI — with a friendly CLI and dev-first architecture."
__author__ = "Renan Siqueira Antonio"
__license__ = "MIT"
Expand Down
118 changes: 63 additions & 55 deletions src/rsazure_openai_toolkit/samples/templates/basic_usage.py.j2
Original file line number Diff line number Diff line change
@@ -1,56 +1,64 @@
import time
from rsazure_openai_toolkit import call_azure_openai_handler
from rsazure_openai_toolkit.utils import get_model_config
from rsazure_openai_toolkit.logging.interaction_logger import InteractionLogger


messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Say hello!"}
]

model_config = get_model_config()
start = time.time()

response = call_azure_openai_handler(
api_key="your-api-key",
azure_endpoint="https://your-resource.openai.azure.com/",
api_version="2023-12-01-preview",
deployment_name="your-deployment-name",
messages=messages,
**model_config
)

elapsed = round(time.time() - start, 2)
content = response.choices[0].message.content
usage = response.usage.model_dump() if response.usage else {}
model_used = response.model
seed_used = model_config.get("seed")

input_tokens = usage.get("prompt_tokens", 0)
output_tokens = usage.get("completion_tokens", 0)
total_tokens = usage.get("total_tokens", input_tokens + output_tokens)

print(f"\nAssistant:\n\t{content}")
print("\n----- REQUEST INFO -----")
print(f"📤 Input tokens: {input_tokens}")
print(f"📥 Output tokens: {output_tokens}")
print(f"🧾 Total tokens: {total_tokens}")
print(f"🧠 Model: {model_used}")
print(f"🎲 Seed: {seed_used}")
print(f"⏱️ Time: {elapsed}s\n")

# Optional logging mode: none [default], jsonl, csv
logger = InteractionLogger(mode="none", path="chat_logs.jsonl")

if logger.enabled:
logger.log({
"question": "Say hello!",
"response": content,
"model": model_used,
"usage": usage,
"model_config": model_config,
"raw_response": response.model_dump()
})
else:
print("📭 Logging is disabled (RSCHAT_LOG_MODE is 'none' or not configured)\n")
import rsazure_openai_toolkit as rschat


def main():
user_input = "Say hello!"
rschat.load_env()

context_data = rschat.get_context_messages(user_input=user_input)
messages = context_data["messages"]

model_config = rschat.get_model_config()
config = rschat.get_cli_config()

start = time.time()
response = rschat.main(
api_key=config["api_key"],
azure_endpoint=config["endpoint"],
api_version=config["version"],
deployment_name=config["deployment_name"],
messages=messages,
**model_config
)
elapsed = round(time.time() - start, 2)

if not response.choices:
print("❌ No response received from the model.")
return

content = response.choices[0].message.content
usage = response.usage.model_dump() if response.usage else {}

input_tokens = usage.get("prompt_tokens", 0)
output_tokens = usage.get("completion_tokens") or rschat.estimate_input_tokens(
messages=[{"role": "assistant", "content": content}],
deployment_name=config["deployment_name"]
)
total_tokens = usage.get("total_tokens", input_tokens + output_tokens)

result = rschat.ChatResult(
question=user_input,
response_text=content,
system_prompt=config["system_prompt"],
model=response.model,
seed=model_config.get("seed"),
input_tokens=input_tokens,
output_tokens=output_tokens,
total_tokens=total_tokens,
elapsed_time=elapsed,
model_config=model_config,
raw_response=response.model_dump()
)

result.print()

logger = rschat.get_logger()
if logger.enabled:
logger.log(result.to_log_dict())
else:
print(f"📭 Logging is disabled ({logger})\n")


if __name__ == "__main__":
main()
93 changes: 51 additions & 42 deletions src/rsazure_openai_toolkit/samples/templates/chat_loop_usage.py.j2
Original file line number Diff line number Diff line change
@@ -1,72 +1,81 @@
import time
from rsazure_openai_toolkit import call_azure_openai_handler
from rsazure_openai_toolkit.utils.utils import get_model_config
from rsazure_openai_toolkit.logging.interaction_logger import InteractionLogger
import rsazure_openai_toolkit as rschat


def chat():
def chat_loop():
print("🔁 Chat loop started")
print("💡 Type 'exit' to quit\n")

# Optional logging mode: none [default], jsonl, csv
logger = InteractionLogger(mode="none", path="chat_logs.jsonl")
# Carrega variáveis de ambiente
rschat.load_env()
config = rschat.get_cli_config()
logger = rschat.get_logger()

while True:
user_input = input("You: ")
if user_input.strip().lower() == "exit":
user_input = input("You: ").strip()
if user_input.lower() == "exit":
print("👋 Goodbye!")
break
if not user_input.strip():
if not user_input:
continue

messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_input}
]
# Prepara mensagens com ou sem contexto persistente
context_data = rschat.get_context_messages(user_input=user_input)
messages = context_data["messages"]

model_config = get_model_config()
start = time.time()
model_config = rschat.get_model_config()

response = call_azure_openai_handler(
api_key="your-api-key",
azure_endpoint="https://your-resource.openai.azure.com/",
api_version="2023-12-01-preview",
deployment_name="your-deployment-name",
start = time.time()
response = rschat.main(
api_key=config["api_key"],
azure_endpoint=config["endpoint"],
api_version=config["version"],
deployment_name=config["deployment_name"],
messages=messages,
**model_config
)

elapsed = round(time.time() - start, 2)

if not response.choices:
print("❌ No response received from the model.")
continue

content = response.choices[0].message.content
usage = response.usage.model_dump() if response.usage else {}
model_used = response.model
seed_used = model_config.get("seed")

input_tokens = usage.get("prompt_tokens", 0)
output_tokens = usage.get("completion_tokens", 0)
output_tokens = usage.get("completion_tokens") or rschat.estimate_input_tokens(
messages=[{"role": "assistant", "content": content}],
deployment_name=config["deployment_name"]
)
total_tokens = usage.get("total_tokens", input_tokens + output_tokens)

print(f"\nAssistant:\n\t{content}")
print("\n----- REQUEST INFO -----")
print(f"📤 Input tokens: {input_tokens}")
print(f"📥 Output tokens: {output_tokens}")
print(f"🧾 Total tokens: {total_tokens}")
print(f"🧠 Model: {model_used}")
print(f"🎲 Seed: {seed_used}")
print(f"⏱️ Time: {elapsed}s\n")
# Constrói resultado e imprime no formato padrão
result = rschat.ChatResult(
question=user_input,
response_text=content,
system_prompt=config["system_prompt"],
model=response.model,
seed=model_config.get("seed"),
input_tokens=input_tokens,
output_tokens=output_tokens,
total_tokens=total_tokens,
elapsed_time=elapsed,
model_config=model_config,
raw_response=response.model_dump()
)

result.print()

if logger.enabled:
logger.log({
"question": user_input,
"response": content,
"model": model_used,
"usage": usage,
"model_config": model_config,
"raw_response": response.model_dump()
})
logger.log(result.to_log_dict())
else:
print("📭 Logging is disabled (RSCHAT_LOG_MODE is 'none' or not configured)\n")
print(f"📭 Logging is disabled ({logger})\n")


def main():
chat_loop()


if __name__ == "__main__":
chat()
main()
Loading