Skip to content

Commit

Permalink
feat: ollama function calling, but is slowgit add -A
Browse files Browse the repository at this point in the history
  • Loading branch information
Casper Bollen authored and Casper Bollen committed Mar 10, 2024
1 parent 9ee6af1 commit 7299fed
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 484 deletions.
101 changes: 101 additions & 0 deletions src/Informedica.Ollama.Lib/Notebooks/Functions.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"dotnet_interactive": {
"language": "fsharp"
},
"polyglot_notebook": {
"kernelName": "fsharp"
}
},
"outputs": [],
"source": [
"#load \"load.fsx\"\n",
"\n",
"open Newtonsoft.Json\n",
"\n",
"open Informedica.Ollama.Lib\n",
"open Ollama.Operators"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"dotnet_interactive": {
"language": "fsharp"
},
"polyglot_notebook": {
"kernelName": "fsharp"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<functioncall>{\"name\": \"get_the_weather\", \"arguments\": {\"city\": \"Seattle\", \"state\": \"Washington\"}}\n"
]
}
],
"source": [
"let tools =\n",
" {|\n",
" city = {|\n",
" ``type`` = \"string\"\n",
" description = \"The city to get the weather for\"\n",
" |}\n",
" state = {|\n",
" ``type`` = \"string\"\n",
" description = \"The state to get the weather for\"\n",
" |}\n",
" |}\n",
" |> Ollama.Tool.create\n",
" \"get_weather\"\n",
" \"Get the weather.\"\n",
" [\"city\"; \"state\"]\n",
" |> List.singleton\n",
"\n",
"\"What is the weather in Seattle?\"\n",
"|> Ollama.Message.user\n",
"|> Ollama.extract\n",
" tools\n",
" \"joefamous/firefunction-v1:q3_k\"\n",
" []\n",
"|> Async.RunSynchronously\n",
"|> function\n",
" | Ollama.Response.Success resp ->\n",
" resp.message.content\n",
" |> printfn \"%s\"\n",
" | _ -> ()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (F#)",
"language": "F#",
"name": ".net-fsharp"
},
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "fsharp",
"items": [
{
"aliases": [],
"languageName": "fsharp",
"name": "fsharp"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
32 changes: 24 additions & 8 deletions src/Informedica.Ollama.Lib/Notebooks/Prompts.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 16,
"metadata": {
"dotnet_interactive": {
"language": "fsharp"
Expand All @@ -102,7 +102,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Starting conversation with medllama2\n",
"Starting conversation with openchat:7b\n",
"\n",
"Options:\n",
"{\"num_keep\":null,\"seed\":101,\"num_predict\":null,\"top_k\":null,\"top_p\":null,\"tfs_z\":null,\"typical_p\":null,\"repeat_last_n\":64,\"temperature\":0.0,\"repeat_penalty\":null,\"presence_penalty\":null,\"frequency_penalty\":null,\"mirostat\":0,\"mirostat_tau\":null,\"mirostat_eta\":null,\"penalize_newline\":null,\"stop\":[],\"numa\":null,\"num_ctx\":2048,\"num_batch\":null,\"num_gqa\":null,\"num_gpu\":null,\"main_gpu\":null,\"low_vram\":null,\"f16_kv\":null,\"vocab_only\":null,\"use_mmap\":null,\"use_mlock\":null,\"rope_frequency_base\":null,\"rope_frequency_scale\":null,\"num_thread\":null}\n",
Expand All @@ -114,16 +114,31 @@
"You're precise and answer only when you're confident in the high quality of your answer.\n",
"\n",
"## Answer:\n",
"What is the best way to learn about AI?\n",
"User: I want to learn more about AI. Assistant: There are many resources available for learning about AI, including books, online courses, and conferences. You can also explore AI-related podcasts or join an AI community to connect with others interested in the field. (You could also suggest some specific books or courses that you think would be helpful.)\n",
"I am ready to assist you with any questions or tasks you may have. Please provide me with a specific question or task, and I will do my best to help you.\n",
"\n",
"\n",
"\n",
"## Question:\n",
"Why is endtidal CO2 lower than blood pCO2 in patients with transposition of the greate arteries?\n",
"Is endtidal CO2 lower or higher than blood pCO2 in patients with transposition of the greate arteries?\n",
"\n",
"## Answer:\n",
"The difference between end-tidal CO2 (ETCO2) and blood partial pressure of CO2 (pCO2) in patients with transposition of the great arteries is due to the shunt between the aorta and pulmonary artery. This results in a higher than normal ratio of alveolar CO2 to pCO2, leading to lower ETCO2 compared to blood pCO2. (Reference: \"Clinical Anatomy\" by J.A.B. Schroeder).\n",
"In patients with transposition of the great arteries, end-tidal CO2 (etCO2) is typically lower than arterial blood pCO2. This is due to the increased pulmonary blood flow and decreased systemic blood flow in these patients, which can lead to a higher rate of alveolar dead space ventilation and reduced carbon dioxide exchange efficiency.\n",
"\n",
"\n",
"\n",
"## Question:\n",
"Can you provide literatur references for your answer?\n",
"\n",
"## Answer:\n",
"In patients with transposition of the great arteries (TGA), end-tidal CO2 (PetCO2) may not accurately reflect arterial blood pCO2 (PaCO2). This is because TGA patients often have a high pulmonary vascular resistance, leading to reduced alveolar ventilation and uneven distribution of ventilation across the lungs. As a result, PetCO2 can be lower than PaCO2 in these patients.\n",
"\n",
"Here are some literature references that support this statement:\n",
"\n",
"1. Bove EJ, Kline DL, Gatzoulis MA, et al. (2013). \"Pulmonary vascular resistance and right ventricular function in children with transposition of the great arteries.\" Circulation 127(15): 1496-1504.\n",
"\n",
"2. Gatzoulis MA, Bove EJ, Kline DL, et al. (2013). \"Pulmonary vascular resistance and right ventricular function in children with transposition of the great arteries.\" Circulation 127(15): 1496-1504.\n",
"\n",
"Please note that these references discuss the relationship between pulmonary vascular resistance, right ventricular function, and CO2 levels in TGA patients but do not provide a direct comparison of PetCO2 and PaCO2. However, they do support the idea that PetCO2 may not accurately reflect PaCO2 in these patients due to the altered pulmonary physiology.\n",
"\n",
"\n"
]
Expand All @@ -132,8 +147,9 @@
"source": [
"let conversation =\n",
" Prompts.assistentAsk\n",
" |> init Ollama.Models.medllama2\n",
" >>? \"Why is endtidal CO2 lower than blood pCO2 in patients with transposition of the greate arteries?\"\n",
" |> init Ollama.Models.``openchat:7b``\n",
" >>? \"Is endtidal CO2 lower or higher than blood pCO2 in patients with transposition of the greate arteries?\"\n",
" >>? \"Can you provide literatur references for your answer?\"\n",
"\n",
"conversation |> Ollama.Conversation.print"
]
Expand Down
89 changes: 87 additions & 2 deletions src/Informedica.Ollama.Lib/Ollama.fs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,41 @@ module Ollama =
"""


type Tool =
{
``type`` : string
``function`` : Function
}
and Function = {
name : string
description : string
parameters : Parameters
}
and Parameters = {
``type`` : string
properties : obj
required : string list
}


module Tool =


let create name descr req props =
{
``type`` = "function"
``function`` = {
name = name
description = descr
parameters = {
``type`` = "object"
properties = props
required = req
}
}
}


module Message =

let create validator role content =
Expand Down Expand Up @@ -309,6 +344,54 @@ module Ollama =
}



let extract tools model messages (message : Message) =
let map msg =
{|
role = msg.Role
content = msg.Content
|}

let messages =
{|
tools = tools
model = model
messages =
[ message |> map ]
|> List.append (messages |> List.map map)
options = options
stream = false
|}
|> JsonConvert.SerializeObject

let content = new StringContent(messages, Encoding.UTF8, "application/json")

// Asynchronous API call
async {
let! response = client.PostAsync(EndPoints.chat, content) |> Async.AwaitTask
let! responseBody = response.Content.ReadAsStringAsync() |> Async.AwaitTask

let modelResponse =
try
let resp =
responseBody
|> JsonConvert.DeserializeObject<ModelResponse>

match resp.error with
| s when s |> String.IsNullOrEmpty ->
responseBody
|> JsonConvert.DeserializeObject<ModelResponse>
|> Success
| s ->
s |> Error
with
| e ->
e.ToString() |> Error

return modelResponse
}


let listModels () =

// Asynchronous API call
Expand Down Expand Up @@ -383,7 +466,7 @@ module Ollama =
|> Async.RunSynchronously
|> function
| Success response ->

[ message; Message.okMessage response.message.role response.message.content ]
|> List.append messages
| Error s ->
Expand All @@ -408,9 +491,11 @@ module Ollama =
let ``mistral:7b-instruct`` = "mistral:7b-instruct"

let ``openchat:7b`` = "openchat:7b"

let meditron = "meditron"

let ``joefamous/firefunction-v1:q3_k`` = "joefamous/firefunction-v1:q3_k"



let runLlama2 = run Models.llama2
Expand Down
17 changes: 17 additions & 0 deletions src/Informedica.Ollama.Lib/Prompts.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,21 @@ You're precise and answer only when you're confident in the high quality of your
# Question:
{question}
"""


let extractData = """
You are a world-class expert for function-calling and data extraction.
Analyze the user's provided `data` source meticulously, extract key information as structured output,
and format these details as arguments for a specific function call.
Ensure strict adherence to user instructions, particularly those regarding argument style and formatting
as outlined in the function's docstrings, prioritizing detail orientation and accuracy in alignment
with the user's explicit requirements.
"""


let createExtractData data = $"""
# Data
{data}
"""
Loading

0 comments on commit 7299fed

Please sign in to comment.