feat: Draft ollama test (#566)
<!-- .github/pull_request_template.md --> ## Description <!-- Provide a clear description of the changes in this PR --> ## DCO Affirmation I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Tests** - Introduced new automated testing workflows for Ollama and Gemini, triggered by pull requests and manual dispatch. - The Ollama workflow sets up the service and executes a simple example test to enhance continuous integration. - Enhanced dependency update workflow with new triggers for push and pull request events, and added an optional debug logging parameter. - Added new capabilities for audio and image transcription within the Ollama API adapter. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Daniel Molnar <soobrosa@gmail.com>
This commit is contained in:
parent
3d4312577e
commit
c496bb485c
4 changed files with 224 additions and 1 deletions
33
.github/workflows/test_gemini.yml
vendored
Normal file
33
.github/workflows/test_gemini.yml
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
name: test | gemini
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
types: [labeled, synchronize]
|
||||||
|
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run_simple_example_test:
|
||||||
|
uses: ./.github/workflows/reusable_python_example.yml
|
||||||
|
with:
|
||||||
|
example-location: ./examples/python/simple_example.py
|
||||||
|
secrets:
|
||||||
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
|
GRAPHISTRY_USERNAME: ${{ secrets.GRAPHISTRY_USERNAME }}
|
||||||
|
GRAPHISTRY_PASSWORD: ${{ secrets.GRAPHISTRY_PASSWORD }}
|
||||||
|
EMBEDDING_PROVIDER: "gemini"
|
||||||
|
EMBEDDING_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
||||||
|
EMBEDDING_MODEL: "gemini/text-embedding-004"
|
||||||
|
EMBEDDING_ENDPOINT: "https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004"
|
||||||
|
EMBEDDING_API_VERSION: "v1beta"
|
||||||
|
EMBEDDING_DIMENSIONS: 768
|
||||||
|
EMBEDDING_MAX_TOKENS: 8076
|
||||||
|
LLM_PROVIDER: "gemini"
|
||||||
|
LLM_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
||||||
|
LLM_MODEL: "gemini/gemini-1.5-flash"
|
||||||
|
LLM_ENDPOINT: "https://generativelanguage.googleapis.com/"
|
||||||
|
LLM_API_VERSION: "v1beta"
|
||||||
116
.github/workflows/test_ollama.yml
vendored
Normal file
116
.github/workflows/test_ollama.yml
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
name: test | ollama
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
types: [ labeled, synchronize ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
run_simple_example_test:
|
||||||
|
|
||||||
|
# needs 16 Gb RAM for phi4
|
||||||
|
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||||
|
# services:
|
||||||
|
# ollama:
|
||||||
|
# image: ollama/ollama
|
||||||
|
# ports:
|
||||||
|
# - 11434:11434
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.12.x'
|
||||||
|
|
||||||
|
- name: Install Poetry
|
||||||
|
uses: snok/install-poetry@v1.4.1
|
||||||
|
with:
|
||||||
|
virtualenvs-create: true
|
||||||
|
virtualenvs-in-project: true
|
||||||
|
installer-parallel: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
poetry install --no-interaction --all-extras
|
||||||
|
poetry add torch
|
||||||
|
|
||||||
|
# - name: Install ollama
|
||||||
|
# run: curl -fsSL https://ollama.com/install.sh | sh
|
||||||
|
# - name: Run ollama
|
||||||
|
# run: |
|
||||||
|
# ollama serve --openai &
|
||||||
|
# ollama pull llama3.2 &
|
||||||
|
# ollama pull avr/sfr-embedding-mistral:latest
|
||||||
|
|
||||||
|
- name: Start Ollama container
|
||||||
|
run: |
|
||||||
|
docker run -d --name ollama -p 11434:11434 ollama/ollama
|
||||||
|
sleep 5
|
||||||
|
docker exec -d ollama bash -c "ollama serve --openai"
|
||||||
|
|
||||||
|
- name: Check Ollama logs
|
||||||
|
run: docker logs ollama
|
||||||
|
|
||||||
|
- name: Wait for Ollama to be ready
|
||||||
|
run: |
|
||||||
|
for i in {1..30}; do
|
||||||
|
if curl -s http://localhost:11434/v1/models > /dev/null; then
|
||||||
|
echo "Ollama is ready"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Waiting for Ollama... attempt $i"
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "Ollama failed to start"
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
- name: Pull required Ollama models
|
||||||
|
run: |
|
||||||
|
curl -X POST http://localhost:11434/api/pull -d '{"name": "phi4"}'
|
||||||
|
curl -X POST http://localhost:11434/api/pull -d '{"name": "avr/sfr-embedding-mistral:latest"}'
|
||||||
|
|
||||||
|
- name: Call ollama API
|
||||||
|
run: |
|
||||||
|
curl -X POST http://localhost:11434/v1/chat/completions \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"model": "phi4",
|
||||||
|
"stream": false,
|
||||||
|
"messages": [
|
||||||
|
{ "role": "system", "content": "You are a helpful assistant." },
|
||||||
|
{ "role": "user", "content": "Whatever I say, answer with Yes." }
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
curl -X POST http://127.0.0.1:11434/v1/embeddings \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"model": "avr/sfr-embedding-mistral:latest",
|
||||||
|
"input": "This is a test sentence to generate an embedding."
|
||||||
|
}'
|
||||||
|
|
||||||
|
- name: Dump Docker logs
|
||||||
|
run: |
|
||||||
|
docker ps
|
||||||
|
docker logs $(docker ps --filter "ancestor=ollama/ollama" --format "{{.ID}}")
|
||||||
|
|
||||||
|
|
||||||
|
- name: Run example test
|
||||||
|
env:
|
||||||
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
|
GRAPHISTRY_USERNAME: ${{ secrets.GRAPHISTRY_USERNAME }}
|
||||||
|
GRAPHISTRY_PASSWORD: ${{ secrets.GRAPHISTRY_PASSWORD }}
|
||||||
|
PYTHONFAULTHANDLER: 1
|
||||||
|
LLM_PROVIDER: "ollama"
|
||||||
|
LLM_API_KEY: "ollama"
|
||||||
|
LLM_ENDPOINT: "http://localhost:11434/v1/"
|
||||||
|
LLM_MODEL: "phi4"
|
||||||
|
EMBEDDING_PROVIDER: "ollama"
|
||||||
|
EMBEDDING_MODEL: "avr/sfr-embedding-mistral:latest"
|
||||||
|
EMBEDDING_ENDPOINT: "http://localhost:11434/v1/"
|
||||||
|
EMBEDDING_DIMENSIONS: "4096"
|
||||||
|
HUGGINGFACE_TOKENIZER: "Salesforce/SFR-Embedding-Mistral"
|
||||||
|
run: poetry run python ./examples/python/simple_example.py
|
||||||
23
.github/workflows/upgrade_deps.yml
vendored
23
.github/workflows/upgrade_deps.yml
vendored
|
|
@ -2,8 +2,29 @@ name: Update Poetry Dependencies
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 3 * * 0'
|
- cron: '0 3 * * 0' # Runs at 3 AM every Sunday
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'poetry.lock'
|
||||||
|
- 'pyproject.toml'
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'poetry.lock'
|
||||||
|
- 'pyproject.toml'
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
debug_enabled:
|
||||||
|
type: boolean
|
||||||
|
description: 'Run the update with debug logging'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-dependencies:
|
update-dependencies:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import instructor
|
||||||
from cognee.infrastructure.llm.llm_interface import LLMInterface
|
from cognee.infrastructure.llm.llm_interface import LLMInterface
|
||||||
from cognee.infrastructure.llm.config import get_llm_config
|
from cognee.infrastructure.llm.config import get_llm_config
|
||||||
from openai import OpenAI
|
from openai import OpenAI
|
||||||
|
import base64
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class OllamaAPIAdapter(LLMInterface):
|
class OllamaAPIAdapter(LLMInterface):
|
||||||
|
|
@ -42,3 +44,54 @@ class OllamaAPIAdapter(LLMInterface):
|
||||||
)
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def create_transcript(self, input_file: str) -> str:
|
||||||
|
"""Generate an audio transcript from a user query."""
|
||||||
|
|
||||||
|
if not os.path.isfile(input_file):
|
||||||
|
raise FileNotFoundError(f"The file {input_file} does not exist.")
|
||||||
|
|
||||||
|
with open(input_file, "rb") as audio_file:
|
||||||
|
transcription = self.aclient.audio.transcriptions.create(
|
||||||
|
model="whisper-1", # Ensure the correct model for transcription
|
||||||
|
file=audio_file,
|
||||||
|
language="en",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure the response contains a valid transcript
|
||||||
|
if not hasattr(transcription, "text"):
|
||||||
|
raise ValueError("Transcription failed. No text returned.")
|
||||||
|
|
||||||
|
return transcription.text
|
||||||
|
|
||||||
|
def transcribe_image(self, input_file: str) -> str:
|
||||||
|
"""Transcribe content from an image using base64 encoding."""
|
||||||
|
|
||||||
|
if not os.path.isfile(input_file):
|
||||||
|
raise FileNotFoundError(f"The file {input_file} does not exist.")
|
||||||
|
|
||||||
|
with open(input_file, "rb") as image_file:
|
||||||
|
encoded_image = base64.b64encode(image_file.read()).decode("utf-8")
|
||||||
|
|
||||||
|
response = self.aclient.chat.completions.create(
|
||||||
|
model=self.model,
|
||||||
|
messages=[
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": [
|
||||||
|
{"type": "text", "text": "What’s in this image?"},
|
||||||
|
{
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {"url": f"data:image/jpeg;base64,{encoded_image}"},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
max_tokens=300,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure response is valid before accessing .choices[0].message.content
|
||||||
|
if not hasattr(response, "choices") or not response.choices:
|
||||||
|
raise ValueError("Image transcription failed. No response received.")
|
||||||
|
|
||||||
|
return response.choices[0].message.content
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue