Passed
Push — master ( 346cc8...8701d0 )
by Thomas
15:12
created

OllamaTowerInstruct::expandLang()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 11
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 14
rs 9.9
1
<?php
2
3
namespace LeKoala\Multilingual;
4
5
use Exception;
6
7
/**
8
 * A simple ollama client to query towerinstruct model
9
 * @link https://ollama.com/thinkverse/towerinstruct
10
 * @link https://huggingface.co/Unbabel/TowerInstruct-7B-v0.2
11
 */
12
class OllamaTowerInstruct
13
{
14
    final public const BASE_URL = 'http://localhost:11434';
15
    final public const BASE_MODEL = 'thinkverse/towerinstruct';
16
17
    protected ?string $model;
18
    protected ?string $url;
19
20
    public function __construct(?string $model = null, ?string $url = null)
21
    {
22
        $this->model = $model ?? self::BASE_MODEL;
23
        $this->url = $url ?? self::BASE_URL;
24
    }
25
26
    public function expandLang(string $lang): string
27
    {
28
        // English, Portuguese, Spanish, French, German, Dutch, Italian, Korean, Chinese, Russian
29
        return match ($lang) {
30
            'en' => 'English',
31
            'fr' => 'French',
32
            'nl' => 'Dutch',
33
            'it' => 'Italian',
34
            'de' => 'German',
35
            'pt' => 'Portuguese',
36
            'ko' => 'Korean',
37
            'zh' => 'Chinese',
38
            'ru' => 'Russian',
39
            default => $lang
40
        };
41
    }
42
43
    public function translate(?string $string, string $to, string $from)
44
    {
45
        /*
46
        messages = [
47
            {"role": "user", "content": "Translate the following text from Portuguese into English.\nPortuguese: Um grupo de investigadores lançou um novo modelo para tarefas relacionadas com tradução.\nEnglish:"},
48
        ]
49
        */
50
51
        $string = $string ?? '';
52
        $from = $this->expandLang($from);
53
        $to = $this->expandLang($to);
54
55
        $prompt = "Translate the following text from $from into $to and keep variables between {} as is.\n$from: $string\n$to:";
56
57
        $result = $this->generate($prompt);
58
59
        $response = $result['response'] ?? '';
60
61
        // Avoid extra space
62
        $response = trim($response);
63
64
        // Make sure we don't get any extra ending dot
65
        $endsWithDot = str_ends_with($string, '.');
66
        $translationEndsWithDot = str_ends_with($response, '.');
67
        if (!$endsWithDot && $translationEndsWithDot) {
68
            $response = rtrim($response, '.');
69
        }
70
71
        return $response;
72
    }
73
74
    /**
75
     * @param null|array<int> $context
76
     * @return array{model:string,created_at:string,response:string,done:bool,done_reason:string,context:array<int>,total_duration:int,load_duration:int,prompt_eval_count:int,prompt_eval_duration:int,eval_count:int,eval_duration:int}
77
     */
78
    public function generate(string $prompt, ?array $context = null)
79
    {
80
        $data = [
81
            'model' => $this->model,
82
            'prompt' => $prompt,
83
            'stream' => false,
84
        ];
85
        if (!empty($context)) {
86
            $data['context'] = $context;
87
        }
88
89
        $url = $this->url . '/api/generate';
90
        $ch = curl_init();
91
92
        curl_setopt($ch, CURLOPT_URL, $url);
93
        curl_setopt($ch, CURLOPT_POST, true);
94
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
95
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
96
97
        $output = curl_exec($ch);
98
99
        curl_close($ch);
100
101
        $decoded = json_decode($output, true);
0 ignored issues
show
Bug introduced by
It seems like $output can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        $decoded = json_decode(/** @scrutinizer ignore-type */ $output, true);
Loading history...
102
103
        if (!$decoded) {
104
            throw new Exception("Failed to decode json: " . json_last_error_msg());
105
        }
106
107
        //@phpstan-ignore-next-line
108
        return $decoded;
109
    }
110
}
111