diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bb5ad0af..d6202298 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Build Release Artifacts +name: Release on: push: @@ -6,17 +6,11 @@ on: - 'v*' jobs: - build-python-packages: + release-python-packages: runs-on: ubuntu-latest - strategy: - matrix: - include: - - name: hindsight-all - path: hindsight - - name: hindsight-api - path: hindsight-api - - name: hindsight-client - path: hindsight-clients/python + environment: pypi + permissions: + id-token: write steps: - uses: actions/checkout@v4 @@ -31,19 +25,52 @@ jobs: with: python-version-file: ".python-version" - - name: Build ${{ matrix.name }} package - working-directory: ./${{ matrix.path }} + # Build all packages + - name: Build hindsight-client + working-directory: ./hindsight-clients/python run: uv build + - name: Build hindsight-api + working-directory: ./hindsight-api + run: uv build + + - name: Build hindsight-all + working-directory: ./hindsight + run: uv build + + # Publish in order (client and api first, then hindsight-all which depends on them) + - name: Publish hindsight-client to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: ./hindsight-clients/python/dist + skip-existing: true + + - name: Publish hindsight-api to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: ./hindsight-api/dist + skip-existing: true + + - name: Publish hindsight-all to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: ./hindsight/dist + skip-existing: true + + # Upload artifacts for GitHub release - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: python-${{ matrix.name }}-dist - path: ${{ matrix.path }}/dist/* - retention-days: 30 + name: python-packages + path: | + hindsight-clients/python/dist/* + hindsight-api/dist/* + hindsight/dist/* + retention-days: 1 - build-typescript-client: + release-typescript-client: runs-on: ubuntu-latest + environment: npm steps: - uses: actions/checkout@v4 @@ -58,22 +85,28 @@ jobs: working-directory: ./hindsight-clients/typescript run: npm ci - - name: Build TypeScript client + - name: Build working-directory: ./hindsight-clients/typescript run: npm run build - - name: Pack npm package + - name: Publish to npm + working-directory: ./hindsight-clients/typescript + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Pack for GitHub release working-directory: ./hindsight-clients/typescript run: npm pack - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: typescript-client-dist + name: typescript-client path: hindsight-clients/typescript/*.tgz - retention-days: 30 + retention-days: 1 - build-rust-cli: + release-rust-cli: runs-on: ${{ matrix.os }} strategy: matrix: @@ -99,24 +132,6 @@ jobs: with: targets: ${{ matrix.target }} - - name: Cache cargo registry - uses: actions/cache@v4 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v4 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo build - uses: actions/cache@v4 - with: - path: hindsight-cli/target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} - - name: Build working-directory: hindsight-cli run: cargo build --release --target ${{ matrix.target }} @@ -132,9 +147,9 @@ jobs: with: name: rust-cli-${{ matrix.asset_name }} path: artifacts/${{ matrix.asset_name }} - retention-days: 30 + retention-days: 1 - build-docker-images: + release-docker-images: runs-on: ubuntu-latest permissions: contents: read @@ -142,7 +157,6 @@ jobs: strategy: matrix: include: - # All images use the same Dockerfile with different --target - target: api-only image_name: hindsight-api - target: cp-only @@ -192,7 +206,7 @@ jobs: type=semver,pattern={{major}},value=${{ steps.get_version.outputs.VERSION }} type=raw,value=latest - - name: Build and push Docker image + - name: Build and push uses: docker/build-push-action@v6 with: context: . @@ -203,7 +217,7 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - package-helm-chart: + release-helm-chart: runs-on: ubuntu-latest steps: @@ -215,77 +229,21 @@ jobs: version: 'latest' - name: Lint Helm chart - run: | - helm lint helm/hindsight + run: helm lint helm/hindsight - name: Package Helm chart - run: | - helm package helm/hindsight --destination ./helm-packages + run: helm package helm/hindsight --destination ./helm-packages - - name: Upload Helm chart artifact + - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: helm-chart path: helm-packages/*.tgz - retention-days: 30 - - publish-python-packages: - runs-on: ubuntu-latest - needs: [build-python-packages] - environment: pypi - strategy: - max-parallel: 1 - matrix: - include: - # Order matters: client and api first, then hindsight-all (which depends on them) - - name: hindsight-client - - name: hindsight-api - - name: hindsight-all - - steps: - - name: Download ${{ matrix.name }} - uses: actions/download-artifact@v4 - with: - name: python-${{ matrix.name }}-dist - path: ./dist - - - name: Publish ${{ matrix.name }} to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: ./dist - skip-existing: true - - publish-npm-package: - runs-on: ubuntu-latest - needs: [build-typescript-client] - environment: npm - - steps: - - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - working-directory: ./hindsight-clients/typescript - run: npm ci - - - name: Build TypeScript client - working-directory: ./hindsight-clients/typescript - run: npm run build - - - name: Publish to npm - working-directory: ./hindsight-clients/typescript - run: npm publish --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + retention-days: 1 create-github-release: runs-on: ubuntu-latest - needs: [build-python-packages, build-typescript-client, build-rust-cli, build-docker-images, package-helm-chart] + needs: [release-python-packages, release-typescript-client, release-rust-cli, release-docker-images, release-helm-chart] permissions: contents: write @@ -296,76 +254,31 @@ jobs: id: get_version run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT - - name: Download hindsight-all + - name: Download all artifacts uses: actions/download-artifact@v4 with: - name: python-hindsight-all-dist - path: ./artifacts/python-hindsight-all - - - name: Download hindsight-api - uses: actions/download-artifact@v4 - with: - name: python-hindsight-api-dist - path: ./artifacts/python-hindsight-api - - - name: Download hindsight-client - uses: actions/download-artifact@v4 - with: - name: python-hindsight-client-dist - path: ./artifacts/python-hindsight-client - - - name: Download TypeScript Client - uses: actions/download-artifact@v4 - with: - name: typescript-client-dist - path: ./artifacts/typescript-client - - - name: Download Rust CLI (Linux) - uses: actions/download-artifact@v4 - with: - name: rust-cli-hindsight-linux-amd64 - path: ./artifacts/rust-cli-hindsight-linux-amd64 - - - name: Download Rust CLI (macOS Intel) - uses: actions/download-artifact@v4 - with: - name: rust-cli-hindsight-darwin-amd64 - path: ./artifacts/rust-cli-hindsight-darwin-amd64 - - - name: Download Rust CLI (macOS ARM) - uses: actions/download-artifact@v4 - with: - name: rust-cli-hindsight-darwin-arm64 - path: ./artifacts/rust-cli-hindsight-darwin-arm64 - - - name: Download Helm chart - uses: actions/download-artifact@v4 - with: - name: helm-chart - path: ./artifacts/helm-chart + path: ./artifacts - name: Prepare release assets run: | mkdir -p release-assets # Python packages - cp artifacts/python-hindsight-all/* release-assets/ - cp artifacts/python-hindsight-api/* release-assets/ - cp artifacts/python-hindsight-client/* release-assets/ - # TypeScript Client - cp artifacts/typescript-client/*.tgz release-assets/ + cp artifacts/python-packages/hindsight-clients/python/dist/* release-assets/ || true + cp artifacts/python-packages/hindsight-api/dist/* release-assets/ || true + cp artifacts/python-packages/hindsight/dist/* release-assets/ || true + # TypeScript client + cp artifacts/typescript-client/*.tgz release-assets/ || true # Rust CLI binaries - cp artifacts/rust-cli-hindsight-linux-amd64/hindsight-linux-amd64 release-assets/ - cp artifacts/rust-cli-hindsight-darwin-amd64/hindsight-darwin-amd64 release-assets/ - cp artifacts/rust-cli-hindsight-darwin-arm64/hindsight-darwin-arm64 release-assets/ + cp artifacts/rust-cli-hindsight-linux-amd64/hindsight-linux-amd64 release-assets/ || true + cp artifacts/rust-cli-hindsight-darwin-amd64/hindsight-darwin-amd64 release-assets/ || true + cp artifacts/rust-cli-hindsight-darwin-arm64/hindsight-darwin-arm64 release-assets/ || true # Helm chart - cp artifacts/helm-chart/*.tgz release-assets/ + cp artifacts/helm-chart/*.tgz release-assets/ || true + ls -la release-assets/ - name: Generate release notes - id: release_notes run: | cat << 'EOF' > release-notes.md - # Hindsight v${{ steps.get_version.outputs.VERSION }} - ## Quick Start ```bash @@ -376,70 +289,29 @@ jobs: ghcr.io/${{ github.repository_owner }}/hindsight:${{ steps.get_version.outputs.VERSION }} ``` - ## 📦 Release Artifacts - - ### Docker Images - - `ghcr.io/${{ github.repository_owner }}/hindsight:${{ steps.get_version.outputs.VERSION }}` - **Standalone all-in-one** (recommended) - - `ghcr.io/${{ github.repository_owner }}/hindsight-api:${{ steps.get_version.outputs.VERSION }}` - API server only + ## Docker Images + - `ghcr.io/${{ github.repository_owner }}/hindsight:${{ steps.get_version.outputs.VERSION }}` - Standalone (recommended) + - `ghcr.io/${{ github.repository_owner }}/hindsight-api:${{ steps.get_version.outputs.VERSION }}` - API only - `ghcr.io/${{ github.repository_owner }}/hindsight-control-plane:${{ steps.get_version.outputs.VERSION }}` - Web UI only - ### Python Packages - - `hindsight-all` - All-in-one package (includes API + client) - - `hindsight-api` - API server - - `hindsight-client` - Client library - - ### TypeScript/JavaScript - - `@vectorize-io/hindsight-client` - TypeScript SDK - - ### CLI Binaries - - `hindsight-linux-amd64` - Linux x86_64 - - `hindsight-darwin-amd64` - macOS Intel - - `hindsight-darwin-arm64` - macOS Apple Silicon - - ### Helm Chart - - `hindsight-${{ steps.get_version.outputs.VERSION }}.tgz` - - ## 🚀 Installation - - ### Python + ## Python ```bash - # All-in-one (recommended) - pip install hindsight-all==${{ steps.get_version.outputs.VERSION }} - - # Or install components separately - pip install hindsight-api==${{ steps.get_version.outputs.VERSION }} - pip install hindsight-client==${{ steps.get_version.outputs.VERSION }} + pip install hindsight-all # or hindsight-api, hindsight-client ``` - ### TypeScript/JavaScript + ## TypeScript/JavaScript ```bash - npm install @vectorize-io/hindsight-client@${{ steps.get_version.outputs.VERSION }} + npm install @vectorize-io/hindsight-client ``` - ### CLI - ```bash - # macOS (Apple Silicon) - curl -L https://github.com/${{ github.repository }}/releases/download/v${{ steps.get_version.outputs.VERSION }}/hindsight-darwin-arm64 -o hindsight - chmod +x hindsight - sudo mv hindsight /usr/local/bin/ + ## CLI + Download the appropriate binary from the release assets below. - # macOS (Intel) - curl -L https://github.com/${{ github.repository }}/releases/download/v${{ steps.get_version.outputs.VERSION }}/hindsight-darwin-amd64 -o hindsight - chmod +x hindsight - sudo mv hindsight /usr/local/bin/ - - # Linux - curl -L https://github.com/${{ github.repository }}/releases/download/v${{ steps.get_version.outputs.VERSION }}/hindsight-linux-amd64 -o hindsight - chmod +x hindsight - sudo mv hindsight /usr/local/bin/ - ``` - - ### Helm (Kubernetes) + ## Helm ```bash helm install hindsight oci://ghcr.io/${{ github.repository_owner }}/charts/hindsight --version ${{ steps.get_version.outputs.VERSION }} ``` EOF - cat release-notes.md - name: Create GitHub Release uses: softprops/action-gh-release@v2 @@ -448,19 +320,5 @@ jobs: body_path: release-notes.md draft: false prerelease: false - generate_release_notes: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Create release summary - run: | - echo "# Release v${{ steps.get_version.outputs.VERSION }} Published Successfully" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "## 📦 Components" >> $GITHUB_STEP_SUMMARY - echo "- ✅ Python packages (hindsight-all, hindsight-api, hindsight-client)" >> $GITHUB_STEP_SUMMARY - echo "- ✅ TypeScript Client (@vectorize-io/hindsight-client)" >> $GITHUB_STEP_SUMMARY - echo "- ✅ Rust CLI (Linux amd64, macOS amd64, macOS arm64)" >> $GITHUB_STEP_SUMMARY - echo "- ✅ Docker images (standalone, API, Control Plane)" >> $GITHUB_STEP_SUMMARY - echo "- ✅ Helm chart" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "🎉 Release is now available at: https://github.com/${{ github.repository }}/releases/tag/v${{ steps.get_version.outputs.VERSION }}" >> $GITHUB_STEP_SUMMARY diff --git a/hindsight-api/hindsight_api/engine/search/retrieval.py b/hindsight-api/hindsight_api/engine/search/retrieval.py index fdb23a8b..c9b079d9 100644 --- a/hindsight-api/hindsight_api/engine/search/retrieval.py +++ b/hindsight-api/hindsight_api/engine/search/retrieval.py @@ -287,39 +287,7 @@ async def retrieve_temporal( query_emb_str, bank_id, fact_type, start_date, end_date, semantic_threshold ) - import logging - logger = logging.getLogger(__name__) - if not entry_points: - # Check if there are ANY memories with temporal metadata for this bank - total_with_dates = await conn.fetchval( - """SELECT COUNT(*) FROM memory_units - WHERE bank_id = $1 AND fact_type = $2 - AND (occurred_start IS NOT NULL OR occurred_end IS NOT NULL OR mentioned_at IS NOT NULL)""", - bank_id, fact_type - ) - # Check how many have mentioned_at in the range - in_range = await conn.fetchval( - """SELECT COUNT(*) FROM memory_units - WHERE bank_id = $1 AND fact_type = $2 - AND mentioned_at IS NOT NULL AND mentioned_at BETWEEN $3 AND $4""", - bank_id, fact_type, start_date, end_date - ) - # Check semantic similarity of those in range - sample = await conn.fetch( - """SELECT id, text, mentioned_at, 1 - (embedding <=> $1::vector) AS similarity - FROM memory_units - WHERE bank_id = $2 AND fact_type = $3 - AND mentioned_at IS NOT NULL AND mentioned_at BETWEEN $4 AND $5 - AND embedding IS NOT NULL - ORDER BY mentioned_at DESC - LIMIT 5""", - query_emb_str, bank_id, fact_type, start_date, end_date - ) - logger.info(f"[TEMPORAL] No entry points for {bank_id}/{fact_type} in {start_date} to {end_date}.") - logger.info(f"[TEMPORAL] Total with dates: {total_with_dates}, In date range: {in_range}") - for row in sample: - logger.info(f"[TEMPORAL] Sample: {row['text'][:60]}... mentioned_at={row['mentioned_at']} sim={row['similarity']:.3f}") return [] # Calculate temporal scores for entry points @@ -475,9 +443,7 @@ async def retrieve_parallel( """ # Detect temporal constraint from .temporal_extraction import extract_temporal_constraint - import logging import time - logger = logging.getLogger(__name__) temporal_constraint = extract_temporal_constraint( query_text, reference_date=question_date, analyzer=query_analyzer diff --git a/hindsight-control-plane/src/components/data-view.tsx b/hindsight-control-plane/src/components/data-view.tsx index 10dfe590..53e89a59 100644 --- a/hindsight-control-plane/src/components/data-view.tsx +++ b/hindsight-control-plane/src/components/data-view.tsx @@ -506,10 +506,11 @@ export function DataView({ factType }: DataViewProps) { {/* Memory Detail Panel for Table View - Fixed on Right */} {selectedTableMemory && ( -
+
setSelectedTableMemory(null)} + inPanel />
)} diff --git a/hindsight-dev/benchmarks/longmemeval/longmemeval_benchmark.py b/hindsight-dev/benchmarks/longmemeval/longmemeval_benchmark.py index 266bc74c..ed30c611 100644 --- a/hindsight-dev/benchmarks/longmemeval/longmemeval_benchmark.py +++ b/hindsight-dev/benchmarks/longmemeval/longmemeval_benchmark.py @@ -174,7 +174,7 @@ class LongMemEvalAnswerGenerator(LLMAnswerGenerator): **How to Answer:** 1. Start by scanning retrieved context to understand the facts and events that happened and the timeline. -2. Reason about all the memories and find the right answer, considering the most recent memory as an update of the current facts +2. Reason about all the memories and find the right answer, considering the most recent memory as an update of the current facts. In general the answer must be comprehensive and plenty of details from the retrieved context. @@ -184,7 +184,7 @@ For recommendations/suggestions, use the retrieved context to understand the use For questions asking for help or instructions, consider the users' latest purchases and previous interactions with the assistant to understand which details to focus your answer on (include these references in your answer). For specific number/value questions, use the context to understand what is the most up-to-date number based on recency, but also include the reasoning (in the answer) on previous possible values and why you think are less relevant. For open questions, include as much details as possible from different sources that are relevant. -For questions where a specific entity is mentioned and it's different from your memory, just say the truth, don't make up anything just to fulfill the question. For example, if the question is about a specific sport, you should consider if the memories and the question are about the same sport. +For questions where a specific entity/role is mentioned and it's different from your memory, just say the truth, don't make up anything just to fulfill the question. For example, if the question is about a specific sport, you should consider if the memories and the question are about the same sport. For comparative questions , say you don't know the answer if you don't have information about both sides. (or more sides) For questions related to time/date, carefully review the question date and the memories date to correctly answer the question. For questions related to time/date calculation (e.g. How many days passed between X and Y?), carefully review the memories date to correctly answer the question and only provide an answer if you have information about both X and Y, otherwise say it's not possible to calculate and why. diff --git a/uv.lock b/uv.lock index 677fbaff..44655e25 100644 --- a/uv.lock +++ b/uv.lock @@ -1141,7 +1141,7 @@ provides-extras = ["test"] [[package]] name = "hindsight-api" -version = "0.0.10" +version = "0.0.11" source = { editable = "hindsight-api" } dependencies = [ { name = "alembic" }, @@ -1243,7 +1243,7 @@ dev = [ [[package]] name = "hindsight-client" -version = "0.0.10" +version = "0.0.11" source = { editable = "hindsight-clients/python" } dependencies = [ { name = "aiohttp" }, @@ -1275,7 +1275,7 @@ provides-extras = ["test"] [[package]] name = "hindsight-dev" -version = "0.0.10" +version = "0.0.11" source = { editable = "hindsight-dev" } dependencies = [ { name = "hindsight-api" },