Skip to content
Open
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
30 changes: 30 additions & 0 deletions examples/code_review_agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Code Review Agent

An automated AI code reviewer built with tRPC-Agent SDK, backed by Hy3 LLM.

## Features

- **Structured review**: Bugs, style, security, improvement suggestions
- **SQLite persistence**: All reviews saved to `code_reviews.db`
- **Skills-ready**: Can be extended with CubeSandbox skills for sandboxed execution

## Quick Start

```bash
pip install -e '.[cube]' # from trpc-agent-python root

export TRPC_AGENT_API_KEY=your-hy3-key
export TRPC_AGENT_BASE_URL=http://127.0.0.1:8000/v1
export TRPC_AGENT_MODEL_NAME=tencent/Hy3

python run_agent.py path/to/your/code.py
```

## Architecture

```
User → Code Review Agent (Hy3 LLM)
├── review_code() → Analyze code
├── save_review() → SQLite persistence
└── skills (optional) → CubeSandbox sandbox
```
Empty file.
25 changes: 25 additions & 0 deletions examples/code_review_agent/agent/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from trpc_agent_sdk.agents import LlmAgent
from trpc_agent_sdk.models import LLMModel, OpenAIModel
from trpc_agent_sdk.tools import FunctionTool

from .config import get_model_config
from .prompts import INSTRUCTION
from .tools import review_code, save_review


def _create_model() -> LLMModel:
api_key, url, model_name = get_model_config()
return OpenAIModel(model_name=model_name, api_key=api_key, base_url=url)


def create_agent() -> LlmAgent:
return LlmAgent(
name="code_reviewer",
description="An AI-powered code review agent backed by Hy3.",
model=_create_model(),
instruction=INSTRUCTION,
tools=[
FunctionTool(review_code),
FunctionTool(save_review),
],
)
8 changes: 8 additions & 0 deletions examples/code_review_agent/agent/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import os


def get_model_config():
api_key = os.environ.get("TRPC_AGENT_API_KEY", "EMPTY")
url = os.environ.get("TRPC_AGENT_BASE_URL", "http://127.0.0.1:8000/v1")
model_name = os.environ.get("TRPC_AGENT_MODEL_NAME", "hy3")
return api_key, url, model_name
7 changes: 7 additions & 0 deletions examples/code_review_agent/agent/prompts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
INSTRUCTION = """You are an expert code reviewer. When a user provides code:

1. Use `review_code` to analyze the code and produce a structured review.
2. Use `save_review` to persist the review results to the database.
3. Summarize the most important findings for the user.

Always reference specific line numbers in your findings. Be constructive, not critical."""
59 changes: 59 additions & 0 deletions examples/code_review_agent/agent/tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Code review tools: review code, save results to database."""
import sqlite3
import json
from datetime import datetime

DB_PATH = "code_reviews.db"


def _get_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("""
CREATE TABLE IF NOT EXISTS reviews (
id INTEGER PRIMARY KEY AUTOINCREMENT,
file_path TEXT,
summary TEXT,
bugs TEXT,
improvements TEXT,
score INTEGER,
created_at TEXT
)
""")
return conn


def review_code(code: str, file_path: str = "") -> dict:
"""Analyze code and return structured review.

This is a tool the agent calls — the actual LLM analysis happens
through the agent's model. The returned dict is the structured
output template.
"""
return {
"code_snippet": code[:500],
"file_path": file_path,
"needs_review": True,
}


def save_review(file_path: str, summary: str, bugs: str,
improvements: str, score: int = 0) -> str:
"""Save a code review to the SQLite database.

Args:
file_path: Path to the reviewed file
summary: One-sentence summary
bugs: Bug findings
improvements: Suggested improvements
score: Quality score (0-10)
"""
conn = _get_db()
conn.execute(
"INSERT INTO reviews (file_path, summary, bugs, improvements, score, created_at) "
"VALUES (?, ?, ?, ?, ?, ?)",
(file_path, summary, bugs, improvements, score, datetime.now().isoformat())
)
conn.commit()
count = conn.execute("SELECT COUNT(*) FROM reviews").fetchone()[0]
conn.close()
return f"Review saved. Total reviews in database: {count}"
45 changes: 45 additions & 0 deletions examples/code_review_agent/run_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Run the code review agent.

Usage::

export TRPC_AGENT_API_KEY=your-hy3-key
export TRPC_AGENT_BASE_URL=http://127.0.0.1:8000/v1
python run_agent.py path/to/file.py
"""

import asyncio
import sys

from trpc_agent_sdk.runners import Runner
from trpc_agent_sdk.sessions import InMemorySessionService

from agent.agent import create_agent


async def main():
if len(sys.argv) < 2:
print("Usage: python run_agent.py <filepath>")
sys.exit(1)

filepath = sys.argv[1]
with open(filepath, "r", encoding="utf-8") as f:
code = f.read()

agent = create_agent()
session_service = InMemorySessionService()

prompt = (
f"Please review the following code file ({filepath}).\n"
f"Call review_code first, then save_review with a score from 0-10, "
f"and summarize your findings:\n\n```\n{code[:20000]}\n```"
)

runner = Runner(agent=agent, session_service=session_service)
async for event in runner.run(prompt):
if event.content:
print(event.content, end="", flush=True)
print()


if __name__ == "__main__":
asyncio.run(main())
25 changes: 25 additions & 0 deletions examples/eval_optimization/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Evaluation + Optimization Pipeline

Auto-regression testing and prompt optimization closed loop built with
tRPC-Agent SDK + Hy3 LLM.

## Features

- **Eval cases**: Built-in test cases with keyword-based scoring
- **Auto-regression**: Compare scores across prompt iterations
- **Optimization**: Iterative prompt improvement based on eval feedback
- **Extensible**: Add custom eval cases and scoring functions

## Quick Start

```bash
export TRPC_AGENT_API_KEY=your-key
export TRPC_AGENT_BASE_URL=https://tokenhub.tencentmaas.com/v1
python run_agent.py
```

## Pipeline

```
Eval Cases → score_response → optimize_prompt → new prompt → re-eval → regress
```
Empty file.
31 changes: 31 additions & 0 deletions examples/eval_optimization/agent/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from trpc_agent_sdk.agents import LlmAgent
from trpc_agent_sdk.models import LLMModel, OpenAIModel
from trpc_agent_sdk.tools import FunctionTool
from .config import get_model_config
from .tools import list_eval_cases, score_response, optimize_prompt

INSTRUCTION = """You are an evaluation and prompt optimization assistant.
Run eval test cases with score_response, analyze regressions, and use
optimize_prompt to iteratively improve prompts based on scores.

When a prompt fails tests, analyze why and suggest concrete improvements.
Track baseline scores and compare after each optimization iteration."""


def _create_model() -> LLMModel:
api_key, url, model_name = get_model_config()
return OpenAIModel(model_name=model_name, api_key=api_key, base_url=url)


def create_agent() -> LlmAgent:
return LlmAgent(
name="eval_optimizer",
description="Evaluation + Optimization auto-regression pipeline.",
model=_create_model(),
instruction=INSTRUCTION,
tools=[
FunctionTool(list_eval_cases),
FunctionTool(score_response),
FunctionTool(optimize_prompt),
],
)
7 changes: 7 additions & 0 deletions examples/eval_optimization/agent/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os

def get_model_config():
api_key = os.environ.get("TRPC_AGENT_API_KEY", "EMPTY")
url = os.environ.get("TRPC_AGENT_BASE_URL", "http://127.0.0.1:8000/v1")
model_name = os.environ.get("TRPC_AGENT_MODEL_NAME", "hy3")
return api_key, url, model_name
95 changes: 95 additions & 0 deletions examples/eval_optimization/agent/tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""Evaluation and prompt optimization pipeline tools.

Provides:
- eval_cases registry with expected outputs
- run_eval to execute test cases and score results
- optimize_prompt to iteratively improve prompts based on eval regression
"""

import json
import time
from dataclasses import dataclass, field
from datetime import datetime


@dataclass
class EvalCase:
id: str
input: str
expected_keywords: list[str] = field(default_factory=list)
max_tokens: int = 500
temperature: float = 0.3


@dataclass
class EvalResult:
case_id: str
passed: bool
response: str
score: float # 0.0 - 1.0
missing_keywords: list[str] = field(default_factory=list)
duration_ms: float = 0.0


@dataclass
class PromptVariant:
version: int
prompt: str
avg_score: float = 0.0
eval_count: int = 0
created_at: str = field(default_factory=lambda: datetime.now().isoformat())


# Built-in eval cases — extend by adding more
BUILTIN_CASES = [
EvalCase(id="greet", input="Say hello in one sentence.",
expected_keywords=["hello", "hi"], max_tokens=50),
EvalCase(id="math", input="What is 2+2? Answer with just the number.",
expected_keywords=["4"], max_tokens=20),
EvalCase(id="code", input="Write a Python function that returns the sum of two numbers.",
expected_keywords=["def", "return", "+"], max_tokens=200),
]


def list_eval_cases() -> list[dict]:
"""List all registered evaluation test cases."""
return [{"id": c.id, "input": c.input, "keywords": c.expected_keywords}
for c in BUILTIN_CASES]


def score_response(response: str, expected_keywords: list[str]) -> dict:
"""Score a response against expected keywords. Returns {score, missing}."""
lower = response.lower()
missing = [k for k in expected_keywords if k.lower() not in lower]
hit = len(expected_keywords) - len(missing)
score = hit / len(expected_keywords) if expected_keywords else 1.0
return {"score": round(score, 2), "missing": missing, "hits": hit}


def optimize_prompt(current_prompt: str, eval_scores: list[float],
failure_analysis: str = "") -> dict:
"""Analyze eval scores and suggest prompt optimization.

Returns: {"version": int, "suggested_prompt": str, "analysis": str}
"""
avg = sum(eval_scores) / len(eval_scores) if eval_scores else 0.0

suggestions = []
if avg < 0.5:
suggestions.append("Add explicit formatting instructions.")
if "missing" in failure_analysis.lower():
suggestions.append("Include required output keywords in the prompt.")
if not suggestions:
suggestions.append("Prompt performing well. Minor tuning may help.")

version = int(time.time())
optimized = current_prompt.strip()
if suggestions:
optimized += "\n\nAdditional instructions:\n- " + "\n- ".join(suggestions)

return {
"version": version,
"avg_score": round(avg, 2),
"suggestions": suggestions,
"suggested_prompt": optimized,
}
35 changes: 35 additions & 0 deletions examples/eval_optimization/run_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Evaluation + Optimization auto-regression pipeline.

Usage::

export TRPC_AGENT_API_KEY=your-key
export TRPC_AGENT_BASE_URL=https://tokenhub.tencentmaas.com/v1
python run_agent.py
"""

import asyncio
from trpc_agent_sdk.runners import Runner
from trpc_agent_sdk.sessions import InMemorySessionService
from agent.agent import create_agent


async def main():
agent = create_agent()
session_service = InMemorySessionService()

prompt = (
"List eval cases, then score this response against the 'greet' case "
"(expected keywords: hello, hi): 'Hey there!'. "
"Finally run optimize_prompt with the current prompt: "
"'You are a helpful assistant' and eval scores [0.6, 0.8, 0.5]."
)

runner = Runner(agent=agent, session_service=session_service)
async for event in runner.run(prompt):
if event.content:
print(event.content, end="", flush=True)
print()


if __name__ == "__main__":
asyncio.run(main())
Loading
Loading