| Crates.io | hefa-core |
| lib.rs | hefa-core |
| version | 0.1.0 |
| created_at | 2025-11-16 11:38:30.278459+00 |
| updated_at | 2025-11-16 11:38:30.278459+00 |
| description | Rust LLM foundation: provider abstraction, tools, structured output, tracing. |
| homepage | https://github.com/kitfactory/hefa-core |
| repository | https://github.com/kitfactory/hefa-core |
| max_upload_size | |
| id | 1935416 |
| size | 150,675 |
Rust 製 LLM 基盤ライブラリ。設計や詳細仕様は docs/ を参照してください。
.env.example をコピーして .env を作成し、必要な API キーを設定します。cargo fmt / cargo clippy / cargo test で品質を維持します。docs/hefa-core-spec.md 要件定義docs/AGENTS.md Agent 層仕様docs/PLAN.md 実装チェックリストOPENAI_API_KEY は環境変数として既に投入済みなので .env には記載せず、そのまま利用してください。openai/gpt-oss-20b モデルを OpenAI 互換エンドポイント経由で利用可能。gpt-oss:20b モデルを利用可能。Agent では hefa_core::Tracer を差し替えることでトレースの保存先を切り替えられます。
use hefa_core::{StdoutTracer, SqliteTracer};
let tracer = StdoutTracer::default(); // 開発時は標準出力
// もしくは永続化
let tracer = SqliteTracer::new("trace.db")?;
let agent = agent.with_tracer(std::sync::Arc::new(tracer));
SqliteTracer には list_recent_spans / list_events があり、SQLite 上に保存された span / event の検索が可能です。
hefa_core::LLMClient はプロバイダ種別に応じて自動で OpenAI Responses API / OpenAI 互換 ChatCompletion API を呼び分けます。以下は「エンジニアの日報からリリースノートのドラフトを作る」例です。
use hefa_core::{
llm::StructuredOutput, Agent, AgentConfig, ProviderKind, Tool, ToolError, ToolResult,
};
use async_trait::async_trait;
use serde_json::{json, Value};
/// Tool used when LLM asks for metadata to enrich the release note.
/// LLM が「リリースノートの下書きを作って」と要求した際に呼ばれる Hook。
struct ReleaseNoteTool;
#[async_trait]
impl Tool for ReleaseNoteTool {
fn name(&self) -> &'static str {
"release_note"
}
fn json_schema(&self) -> Value {
json!({
"type": "object",
"properties": {
"feature": { "type": "string" },
"impact": { "type": "string" }
},
"required": ["feature", "impact"]
})
}
async fn call(&self, args: Value) -> Result<ToolResult, ToolError> {
let feature = args
.get("feature")
.and_then(Value::as_str)
.ok_or_else(|| ToolError::InvalidInput("missing feature".into()))?;
let impact = args
.get("impact")
.and_then(Value::as_str)
.ok_or_else(|| ToolError::InvalidInput("missing impact".into()))?;
Ok(ToolResult {
content: json!({ "draft": format!("Feature: {feature} — Impact: {impact}") }),
})
}
}
let structured_output = StructuredOutput::new(json!({
"type": "object",
"properties": {
"summary": { "type": "string" }
}
}));
let mut agent = Agent::new(AgentConfig {
instruction: "You are a release-note assistant. Respond in 1 sentence.".into(),
provider: ProviderKind::OpenAi,
model: "gpt-4o-mini".into(),
structured_output: Some(structured_output),
tools: vec![Box::new(ReleaseNoteTool)],
})?;
let prompt = "Update: Added offline search with 50% faster indexing.";
let result = agent.invoke(prompt).await?;
println!("Release note: {}", result.response.content);
出力例:
Release note: OK — Feature: Added offline search with 50% faster indexing.
ステップ1 – LLM 選択 & Hello
まずは Provider とモデルを決め、最小構成の Agent で “Hello” を返す例 (examples/basic_agent.rs) を実行します。
cargo run --example basic_agent
ステップ2 – Tool 追加
examples/tool_agent.rs では LLM の tool_calls を処理する Hook を登録し、ReleaseNoteTool で外部ロジックを呼び出す流れを体験します。
cargo run --example tool_agent
ステップ3 – 構造化出力
JSON Schema を指定して LLM の最終回答を構造化する例は examples/structured_agent.rs で確認できます。README で紹介した StructuredOutput::from_type::<T>() も併用してください。
cargo run --example structured_agent
ステップ4 – トレース
examples/trace_agent.rs は SqliteTracer を使って span / event を保存し、list_recent_spans で属性フィルタ(例: instruction に “release” が含まれる)をかけて検索する例です。Tracer には start_trace / start_child_span / record_event が用意されており、Agent はこれらを内部で呼び出します。
cargo run --example trace_agent
ステップ5 – Release Note Agent (統合)
examples/release_note.rs で、Tool + 構造化出力 + トレースの統合例を確認できます。
cargo run --example release_note
OpenAI / LM Studio / Ollama に接続する実機テストは tests/live_llm.rs にあります。
以下の環境変数をセットして個別に実行してください。
HEFA_LIVE_OPENAI=1 cargo test live_openai_responses
HEFA_LIVE_LMSTUDIO=1 LMSTUDIO_API_BASE=http://192.168.11.16:1234/v1 cargo test live_lmstudio_chat
HEFA_LIVE_OLLAMA=1 OLLAMA_API_BASE=http://192.168.11.16:11434 cargo test live_ollama_chat
schemars 連携Feature schema を有効にすると、schemars::JsonSchema を derive した型から
StructuredOutput::from_type::<T>() で JSON Schema を生成できます。LLM へ構造化出力を要求する際に役立ちます。
cargo add schemars --features derive
cargo test --features schema
use hefa_core::llm::StructuredOutput;
use schemars::JsonSchema;
use serde::Serialize;
#[derive(Serialize, JsonSchema)]
struct MyAnswer {
summary: String,
tags: Vec<String>,
}
let output = StructuredOutput::from_type::<MyAnswer>();
TBD