Skip to content
Draft
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
101 changes: 90 additions & 11 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,51 @@
# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist
#
# Copyright 2022-2024, axodotdev
# SPDX-License-Identifier: MIT or Apache-2.0
#
# CI that:
#
# * checks for a Git Tag that looks like a release
# * builds artifacts with dist (archives, installers, hashes)
# * uploads those artifacts to temporary workflow zip
# * on success, uploads the artifacts to a GitHub Release
#
# Note that the GitHub Release will be created with a generated
# title/body based on your changelogs.

name: Release
permissions:
contents: "write"
"contents": "write"

# This task will run whenever you push a git tag that looks like a version
# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
#
# If PACKAGE_NAME is specified, then the announcement will be for that
# package (erroring out if it doesn't have the given version or isn't dist-able).
#
# If PACKAGE_NAME isn't specified, then the announcement will be for all
# (dist-able) packages in the workspace with that version (this mode is
# intended for workspaces with only one dist-able package, or with all dist-able
# packages versioned/released in lockstep).
#
# If you push multiple tags at once, separate instances of this workflow will
# spin up, creating an independent announcement for each one. However, GitHub
# will hard limit this to 3 tags per commit, as it will assume more tags is a
# mistake.
#
# If there's a prerelease-style suffix to the version, then the release(s)
# will be marked as a prerelease.
on:
pull_request:
push:
tags:
- '**[0-9]+.[0-9]+.[0-9]+*'

jobs:
# 1. Plan Job (Linux에서 실행됨 - 버전 v0.30.3 유지)
# Run 'dist plan' (or host) to determine what tasks we need to do
plan:
runs-on: "ubuntu-22.04"
outputs:
Expand All @@ -25,14 +61,20 @@ jobs:
persist-credentials: false
submodules: recursive
- name: Install dist
# we specify bash to get pipefail; it guards against the `curl` command
# failing. otherwise `sh` won't catch that `curl` returned non-0
shell: bash
# 🔥 [중요] 사용자님의 원래 버전(v0.30.3)으로 복구하여 에러 127 해결
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.30.3/cargo-dist-installer.sh | sh"
- name: Cache dist
uses: actions/upload-artifact@v4
with:
name: cargo-dist-cache
path: ~/.cargo/bin/dist
# sure would be cool if github gave us proper conditionals...
# so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
# functionality based on whether this is a pull_request, and whether it's from a fork.
# (PRs run on the *source* but secrets are usually on the *target* -- that's *good*
# but also really annoying to build CI around when it needs secrets to work right.)
- id: plan
run: |
dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json
Expand All @@ -45,26 +87,36 @@ jobs:
name: artifacts-plan-dist-manifest
path: plan-dist-manifest.json

# 2. Build Job (윈도우 설정 추가됨)
# Build and packages all the platform-specific things
build-local-artifacts:
name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
# Let the initial task tell us to not run (currently very blunt)
needs:
- plan
if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }}
strategy:
fail-fast: false
# Target platforms/runners are computed by dist in create-release.
# Each member of the matrix has the following arguments:
#
# - runner: the github runner
# - dist-args: cli flags to pass to dist
# - install-dist: expression to run to install dist on the runner
#
# Typically there will be:
# - 1 "global" task that builds universal installers
# - N "local" tasks that build each platform's binaries and platform-specific installers
matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }}
runs-on: ${{ matrix.runner }}
container: ${{ matrix.container && matrix.container.image || null }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json
steps:
# 🔥 [수정됨] 윈도우 빌드 실패 방지 (Linux 127 에러 방지를 위해 조건문 강화)
- name: enable windows longpaths
if: ${{ runner.os == 'Windows' }}
run: git config --system core.longpaths true

run: |
git config --global core.longpaths true
- uses: actions/checkout@v4
with:
persist-credentials: false
Expand All @@ -78,6 +130,7 @@ jobs:
fi
- name: Install dist
run: ${{ matrix.install_dist.run }}
# Get the dist-manifest
- name: Fetch local artifacts
uses: actions/download-artifact@v4
with:
Expand All @@ -88,16 +141,29 @@ jobs:
run: |
${{ matrix.packages_install }}
- name: Build artifacts
shell: bash
run: |
dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
# Actually do builds and make zips and whatnot
# For Windows builds, disable embeddings feature due to ONNX Runtime compatibility issues
TARGETS="${{ join(matrix.targets, ' ') }}"
if [[ "$TARGETS" == *"windows"* ]]; then
dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} --no-default-features > dist-manifest.json
else
dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
fi
echo "dist ran successfully"
- id: cargo-dist
name: Post-build
# We force bash here just because github makes it really hard to get values up
# to "real" actions without writing to env-vars, and writing to env-vars has
# inconsistent syntax between shell and powershell.
shell: bash
run: |
# Parse out what we just built and upload it to scratch storage
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"

cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts"
uses: actions/upload-artifact@v4
Expand All @@ -107,7 +173,7 @@ jobs:
${{ steps.cargo-dist.outputs.paths }}
${{ env.BUILD_MANIFEST_NAME }}

# 3. Global Build Job (그대로 유지)
# Build and package all the platform-agnostic(ish) things
build-global-artifacts:
needs:
- plan
Expand All @@ -127,6 +193,7 @@ jobs:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Get all the local artifacts for the global tasks to use (for e.g. checksums)
- name: Fetch local artifacts
uses: actions/download-artifact@v4
with:
Expand All @@ -138,9 +205,12 @@ jobs:
run: |
dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
echo "dist ran successfully"

# Parse out what we just built and upload it to scratch storage
echo "paths<<EOF" >> "$GITHUB_OUTPUT"
jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"

cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts"
uses: actions/upload-artifact@v4
Expand All @@ -149,13 +219,13 @@ jobs:
path: |
${{ steps.cargo-dist.outputs.paths }}
${{ env.BUILD_MANIFEST_NAME }}

# 4. Host Job (배포 - 그대로 유지)
# Determines if we should publish/announce
host:
needs:
- plan
- build-local-artifacts
- build-global-artifacts
# Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine)
if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -173,6 +243,7 @@ jobs:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Fetch artifacts from scratch-storage
- name: Fetch artifacts
uses: actions/download-artifact@v4
with:
Expand All @@ -189,8 +260,10 @@ jobs:
- name: "Upload dist-manifest.json"
uses: actions/upload-artifact@v4
with:
# Overwrite the previous copy
name: artifacts-dist-manifest
path: dist-manifest.json
# Create a GitHub Release while uploading all files to it
- name: "Download GitHub Artifacts"
uses: actions/download-artifact@v4
with:
Expand All @@ -199,6 +272,7 @@ jobs:
merge-multiple: true
- name: Cleanup
run: |
# Remove the granular manifests
rm -f artifacts/*-dist-manifest.json
- name: Create GitHub Release
env:
Expand All @@ -207,13 +281,18 @@ jobs:
ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}"
RELEASE_COMMIT: "${{ github.sha }}"
run: |
# Write and read notes from a file to avoid quoting breaking things
echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt

gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/*

announce:
needs:
- plan
- host
# use "always() && ..." to allow us to wait for all publish jobs while
# still allowing individual publish jobs to skip themselves (for prereleases).
# "host" however must run to completion, no skipping allowed!
if: ${{ always() && needs.host.result == 'success' }}
runs-on: "ubuntu-22.04"
env:
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ categories = ["command-line-utilities", "development-tools", "text-processing"]
name = "amdb"
path = "src/main.rs"

[features]
default = ["embeddings"]
embeddings = ["dep:fastembed"]

[dependencies]
clap = { version = "4.4", features = ["derive"] }
console = "0.15"
Expand Down Expand Up @@ -44,7 +48,7 @@ serde_json = "1.0"
axum = "0.7"
regex = "1.10"
lazy_static = "1.4"
fastembed = "4"
fastembed = { version = "4", optional = true }
ordered-float = "4.0"
toml = "0.8"
bincode = "1.3"
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ curl --proto '=https' --tlsv1.2 -LsSf https://github.com/BETAER-08/amdb/releases
### Option 2: Manual Download
Prefer to download the file yourself? Go to the Releases Page and download the version for your OS.

**📌 Windows Users:** Windows binaries are built without the embeddings feature due to ONNX Runtime compatibility issues. The Focus Mode (vector search) feature is not available on Windows, but all other functionality works normally.

### Option 3: Install via Cargo
If you have the Rust toolchain installed:

```bash
# Default installation (includes embeddings on non-Windows platforms)
cargo install amdb

# Windows or without embeddings
cargo install amdb --no-default-features
```

## 🚀 Quick Start
Expand Down Expand Up @@ -62,6 +68,8 @@ amdb generate

For large projects, a full context might be too big. Use **Focus Mode** to generate a summary relevant to a specific feature or bug. `amdb` uses vector search to find the most relevant files.

**⚠️ Note:** This feature requires the `embeddings` feature which is not available on Windows builds due to dependency compatibility issues.

```bash
# Example: generating context for authentication logic
amdb generate --focus "login authentication jwt"
Expand Down
4 changes: 3 additions & 1 deletion dist-workspace.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ ci = "github"
# The installers to generate for each app
installers = []
# Target platforms to build apps for (Rust target-triple syntax)
targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu",]
targets = ["aarch64-apple-darwin", "aarch64-pc-windows-msvc", "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-pc-windows-msvc", "x86_64-unknown-linux-gnu"]
# Skip checking whether the specified configuration files are up to date
allow-dirty = ["ci"]
33 changes: 26 additions & 7 deletions src/core/embedding.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
use anyhow::Result;

#[cfg(feature = "embeddings")]
use fastembed::{TextEmbedding, InitOptions, EmbeddingModel};

pub struct EmbeddingEngine {
#[cfg(feature = "embeddings")]
model: TextEmbedding,
}

impl EmbeddingEngine {
pub fn new() -> Result<Self> {
let mut options = InitOptions::new(EmbeddingModel::BGESmallENV15);
options.show_download_progress = true;
#[cfg(feature = "embeddings")]
{
let mut options = InitOptions::new(EmbeddingModel::BGESmallENV15);
options.show_download_progress = true;

let model = TextEmbedding::try_new(options)?;
Ok(Self { model })
let model = TextEmbedding::try_new(options)?;
Ok(Self { model })
}

#[cfg(not(feature = "embeddings"))]
{
Ok(Self {})
}
}

pub fn embed(&self, text: &str) -> Result<Vec<f32>> {
let documents = vec![text.to_string()];
let embeddings = self.model.embed(documents, None)?;
Ok(embeddings[0].clone())
#[cfg(feature = "embeddings")]
{
let documents = vec![text.to_string()];
let embeddings = self.model.embed(documents, None)?;
Ok(embeddings[0].clone())
}

#[cfg(not(feature = "embeddings"))]
{
anyhow::bail!("Embedding feature is not available. On Windows, embeddings are not supported due to ONNX Runtime dependency limitations. On other platforms, rebuild with default features enabled.")
}
}
}